使用接口variables

我仍然试图更好地理解接口。 我知道他们是什么以及如何在课堂上实施他们。

我不明白的是当你创build一个你的接口types的variables:

IMyInterface somevariable; 

你为什么要这样做? 我不明白IMyInterface如何像类一样使用…例如调用方法,所以:

 somevariable.CallSomeMethod(); 

为什么你会使用IMyInterfacevariables来做到这一点?

您不是创build接口的实例 – 您正在创build一个实现接口的实例。

接口的要点是它保证了实现它的东西将提供在其中声明的方法。

所以,现在,用你的例子,你可以有:

 MyNiftyClass : IMyInterface { public void CallSomeMethod() { //Do something nifty } } MyOddClass : IMyInterface { public void CallSomeMethod() { //Do something odd } } 

现在你有:

 IMyInterface nifty = new MyNiftyClass() IMyInterface odd = new MyOddClass() 

调用CallSomeMethod方法现在可以完成一些奇妙的事情或者奇怪的事情,当你使用IMyInterface作为types传递时,这变得特别有用。

 public void ThisMethodShowsHowItWorks(IMyInterface someObject) { someObject.CallSomeMethod(); } 

现在,根据你是否调用一个漂亮的或奇怪的类的上述方法,你会得到不同的行为。

 public void AnotherClass() { IMyInterface nifty = new MyNiftyClass() IMyInterface odd = new MyOddClass() // Pass in the nifty class to do something nifty this.ThisMethodShowsHowItWorks(nifty); // Pass in the odd class to do something odd this.ThisMethodShowsHowItWorks(odd); } 

编辑

这解决了我认为你想要的问题是 – 为什么你会声明一个variables是一个接口types?

那就是为什么使用:

 IMyInterface foo = new MyConcreteClass(); 

优先于:

 MyConcreteClass foo = new MyConcreteClass(); 

希望你明白为什么在声明一个方法签名的时候会使用这个接口,但是这留下了关于本地作用域variables的问题:

 public void AMethod() { // Why use this? IMyInterface foo = new MyConcreteClass(); // Why not use this? MyConcreteClass bar = new MyConcreteClass(); } 

通常没有技术上的理由为什么接口是首选。 我通常使用的界面,因为:

  • 我通常注入依赖关系,因此需要多态性
  • 使用界面清楚地表明我的意图只使用界面的成员

技术上需要接口的地方就是使用多态的地方,例如使用工厂或使用dependency injection(如上所述)创buildvariables。

借用itowlson的一个例子,使用具体的声明你不能这样做:

 public void AMethod(string input) { IMyInterface foo; if (input == "nifty") { foo = new MyNiftyClass(); } else { foo = new MyOddClass(); } foo.CallSomeMethod(); } 

因为这:

 public void ReadItemsList(List<string> items); public void ReadItemsArray(string[] items); 

可以变成这样:

 public void ReadItems(IEnumerable<string> items); 

编辑

像这样想:

你必须能够做到这一点。

而不是:

你必须是这个。

本质上这是方法和它的调用者之间的契约。

可以说你有class船,汽车,卡车,飞机。

这些都共享一个共同的方法TakeMeThere(string目的地)

你将有一个接口:

 public interface ITransportation { public void TakeMeThere(string destination); } 

那么你的class级:

 public class Boat : ITransportation { public void TakeMeThere(string destination) // From ITransportation { Console.WriteLine("Going to " + destination); } } 

你在这里说的是,我的class级将做所有的传送也告诉我。

然后,当你想为运输公司制作软件。 你可以有一个方法

 Void ProvideServiceForClient(ITransportation transportationMethod, string whereTheyWantToGo) { transportationMethod.TakeMeThere(whereTheyWantToGo); // Cause ITransportation has this method } 

所以,他们想要什么types的交通并不重要,因为我们知道它可以TakeMeThere

使用接口variables是允许编写处理程序方法的唯一方法,它可以接受来自具有不同基类的对象的数据。

这是任何人都会明白的。

我处于相同的位置,花了几天的时间才弄清楚为什么我们不得不使用接口variables。

  IDepartments rep = new DepartmentsImpl(); 

为什么不

  DepartmentsImpl rep = new DepartmentsImpl(); 

想象一下,如果一个类实现了两个包含具有相同签名的成员的接口,那么在该类上实现该成员将导致这两个接口都将该成员用作其实现。

 class Test { static void Main() { SampleClass sc = new SampleClass(); IControl ctrl = (IControl)sc; ISurface srfc = (ISurface)sc; // The following lines all call the same method. sc.Paint(); ctrl.Paint(); srfc.Paint(); } 

}

 interface IControl { void Paint(); } interface ISurface { void Paint(); } class SampleClass : IControl, ISurface { // Both ISurface.Paint and IControl.Paint call this method. public void Paint() { Console.WriteLine("Paint method in SampleClass"); } 

}

  // Output: // Paint method in SampleClass // Paint method in SampleClass // Paint method in SampleClass 

但是,如果两个接口成员不执行相同的function,则可能导致一个或两个接口的错误实现。

 public class SampleClass : IControl, ISurface { void IControl.Paint() { System.Console.WriteLine("IControl.Paint"); } void ISurface.Paint() { System.Console.WriteLine("ISurface.Paint"); } } 

类成员IControl.Paint只能通过IControl接口使用,ISurface.Paint只能通过ISurface使用。 这两种方法的实现是分开的,都不能直接在类上使用。 例如:

  IControl c = new SampleClass(); ISurface s = new SampleClass(); s.Paint(); 

如果我错了,请纠正我,因为我仍然在学习这个接口概念。

这不是特定于C#,所以我build议移动到其他国旗。 对于你的问题,我们select接口的主要原因是在两个组件之间提供协议(可以是dll,jar或其他任何组件)。 请参阅下面

  public class TestClass { static void Main() { IMyInterface ob1, obj2; ob1 = getIMyInterfaceObj(); obj2 = getIMyInterfaceObj(); Console.WriteLine(ob1.CallSomeMethod()); Console.WriteLine(obj2.CallSomeMethod()); Console.ReadLine(); } private static bool isfirstTime = true; private static IMyInterface getIMyInterfaceObj() { if (isfirstTime) { isfirstTime = false; return new ImplementingClass1(); } else { return new ImplementingClass2(); } } } public class ImplementingClass1 : IMyInterface { public ImplementingClass1() { } #region IMyInterface Members public bool CallSomeMethod() { return true; } #endregion } public class ImplementingClass2 : IMyInterface { public ImplementingClass2() { } #region IMyInterface Members public bool CallSomeMethod() { return false; } #endregion } public interface IMyInterface { bool CallSomeMethod(); } 

这里的主要方法并不知道类仍然可以使用接口获得不同的行为。

使用一个接口,所以你不必担心什么类实现接口。 一个有用的例子是当你有一个工厂方法返回一个具体的实现,这个实现可能根据你所运行的环境而有所不同。它还允许APIdevise者定义API,同时允许第三方实现API任何他们认为合适的方式。 Sun使用Java的encryptionAPI来执行此操作。

 public interface Foo { } public class FooFactory { public static Foo getInstance() { if(os == 'Windows') return new WinFoo(); else if(os == 'OS X') return new MacFoo(); else return new GenricFoo(); } } 

你使用工厂的代码只需要知道Foo,而不是任何具体的实现。

接口的目的是定义几个对象之间的契约,而不依赖于具体的实现。

所以当你有一个Intrace ISomething和一个特定的实现时,你通常会使用它

 class Something : ISomething 

所以当你实例化一个契约时,接口variables会被使用:

 ISomething myObj = new Something(); myObj.SomeFunc(); 

你也应该阅读接口C#

更新:

我将通过一个(现实生活)的例子来解释为variables使用接口而不是类本身的逻辑:

我有一个通用的存储器接口:

 Interface IRepository { void Create(); void Update(); } 

我有2个独立的实现:

 class RepositoryFile : interface IRepository {} class RepositoryDB : interface IRepository {} 

每个类都有一个完全不同的内部实现。

现在我有另一个对象,一个logging器,使用一个已经instansiated存储库来做他的写作。 这个对象并不关心Repository是如何实现的,所以他只是实现了:

 void WriteLog(string Log, IRepository oRep); 

顺便说一句,这也可以通过使用标准的类inheritance来实现。 但是使用接口和类inheritance的区别是另外一个讨论。

有关抽象类和接口之间的区别的更多细节讨论,请看这里 。

比方说,你有两个class: BookNewspaper 。 你可以阅读其中每一个,但这两个从一个普通的超类inheritance是没有意义的。 所以他们都会实现IReadable接口:

 public interface IReadable { public void Read(); } 

现在说,你正在写一个应用程序,将阅读用户的书籍和报纸。 用户可以从列表中select一本书或报纸,并将该项目读取给用户。

在你的应用程序读取给用户的方法将把这BookNewspaper作为参数。 这可能看起来像这样的代码:

 public static void ReadItem(IReadable item) { item.Read(); } 

由于该参数是一个IReadable ,我们知道该对象具有Read()方法,因此我们称之为将其读取给用户。 无论这是一BookNewspaper还是其他实现IReadable其他内容都IReadable 。 各个类通过实现Read()方法来精确地实现每个项目的Read()方式,因为对于不同的类,它们很可能是不同的。

BookRead()可能如下所示:

 public void Read() { this.Open(); this.TurnToPage(1); while(!this.AtLastPage) { ReadText(this.CurrentPage.Text); this.TurnPage(); } this.Close(); } 

NewspaperRead()可能会有点不同:

 public void Read() { while(!this.OnBackPage) { foreach(Article article in this.CurrentPage.Articles) { ReadText(article.Text); } } } 

重点是,一个接口types的variables包含的对象保证有一组特定的方法,即使这个对象的可能的类没有以任何其他方式相关。 这使您可以编写适用于各种可以在其上执行常用操作的类的代码。

不,这是不可能的。 devise师没有提供一个方法。 当然,这也是常识。 因为接口仅包含抽象方法,而抽象方法没有实现代码的主体,所以我们不能创build一个对象。

假设即使允许,有什么用。 用对象调用抽象方法不会产生任何目的,因为没有输出。 没有function来抽象方法。 那么,Javadevise和编码中接口的用法是什么? 它们可以用作原型,从而可以轻松开发新课程。 它们像其他类的模板一样工作,像其他类一样实现接口,就像蓝图一样构build一个build筑物。

我相信每个人都在回答使用接口的多态原因,David Hall部分地涉及到了为什么要将其作为接口引用而不是实际的对象名称。 当然,限于接口成员等是有益的,但另一个答案是dependency injection/实例化。

当您devise应用程序时,如果使用dependency injection,则通常更清洁,更易于pipe理,并且更灵活。 如果你从来没有这样做过,那么你会感到倒退,但是当你开始回溯时,你会希望你有。

dependency injection通常是通过允许类实例化和控制依赖关系来实现的,而你只需要依靠你所需要的对象的接口。

例:

先将应用程序分层。 第1层逻辑,第2层接口,第3层dependency injection。 (每个人都有自己的方式,这只是表演)。

在逻辑层中,您可以引用接口和依赖层,然后最终创build仅基于异物接口的逻辑。

开始了:

 public IEmployee GetEmployee(string id) { IEmployee emp = di.GetInstance<List<IEmployee>>().Where(e => e.Id == id).FirstOrDefault(); emp?.LastAccessTimeStamp = DateTime.Now; return emp; } 

注意上面我们如何使用di.GetInstance从我们的依赖中获取一个对象。 我们在该层的代码永远不会知道或关心Employee对象。 事实上,如果它改变了其他代码,它将永远不会影响我们在这里。 如果IEmployee的接口发生变化,那么我们可能需要更改代码。

问题是,IEmployee emp =永远不知道实际的对象是什么,但知道接口以及如何使用它。 考虑到这一点,当你想使用一个接口而不是一个对象,因为我们永远不知道或有权访问该对象。

这是总结..希望它可以帮助。

这是面向对象编程中的一个基本概念 – 多态。 ( 维基百科 )

简单的答案是,通过使用类A中的接口,可以给A类任何IMyInterface

这也是一种松耦合的forms( 维基百科 ) – 在这里你有很多类,但是它们并不相互依赖 – 只是依赖于它们提供的一组属性和方法(接口)的抽象概念。