在我的开发学习中,我觉得我必须学习更多关于接口的知识。
我经常读到它们,但我似乎无法理解它们。
我读过这样的例子:动物基类,IAnimal接口的东西,如“Walk”,“Run”,“GetLegs”等-但我从来没有工作过,觉得“嘿,我应该在这里使用接口!”
我错过了什么?为什么这个概念对我来说这么难理解!我只是害怕这样一个事实,我可能从来没有意识到一个具体的需要-主要是由于一些缺失的理解他们!这让我觉得我作为一名开发人员缺少了一些东西!如果有人有过这样的经历,并取得了突破,我会很感激一些关于如何理解这个概念的建议。谢谢你!
As several people have probably already answered, interfaces can be used to enforce certain behaviors between classes that will not implement those behaviors the same way. So by implementing an interface you are saying that your class has the behavior of the interface. The IAnimal interface would not be a typical interface because Dog, Cat, Bird, etc. classes are types of animals, and should probably extend it, which is a case of inheritance. Instead, an interface would be more like animal behavior in this case, such as IRunnable, IFlyable, ITrainable, etc.
接口有很多好处,其中一个关键就是可插拔性。例如,声明一个具有List参数的方法将允许传入实现List接口的任何东西,允许开发人员在以后删除和插入不同的列表,而不必重写大量代码。
您可能永远不会使用接口,但如果您正在从头开始设计一个项目,特别是某种类型的框架,您可能会想要熟悉它们。
我建议大家阅读Coad、Mayfield和Kern撰写的《Java设计》中关于接口的章节。它们比一般的介绍性文本解释得好一点。如果你不使用Java,你可以只阅读本章的开头,主要是一些概念。
In my experience the driving force to create interfaces didn't occur until I start doing unit testing with a mocking framework. It became abundantly clear that using interfaces was going to make mocking much easier (since the framework depended on the methods being virtual). Once I started I saw the value of abstracting away the interface to my class from the implementation. Even if I don't create an actual interface, I try now to make my methods virtual (providing an implicit interface that can be overridden).
我发现还有许多其他原因可以加强重构到接口的良好实践,但是单元测试/模拟的事情提供了最初的“顿悟时刻”的实践经验。
EDIT: To clarify, with unit testing and mocking I always have two implementations -- the real, concrete implementation and an alternate mock implementation used in testing. Once you have two implementations, the value of the interface becomes obvious -- deal with it in terms of the interface so you can replace the implementation at any time. In this case I'm replacing it with a mock interface. I know that I can do this without an actual interface if my class is constructed properly, but using an actual interface reinforces this and makes it cleaner (clearer to the reader). Without this impetus, I don't think I would have appreciated the value of interfaces since most of my classes only, ever have a single concrete implementation.
与任何为系统增加灵活性的编程技术一样,接口也增加了一定程度的复杂性。它们通常都很好,而且你可以在任何地方使用它(你可以为你的所有类创建一个接口)——但是这样做,你会创建一个更复杂的系统,更难维护。
像往常一样,这里有一个权衡:灵活性胜过可维护性。哪个更重要?没有答案——这取决于项目本身。但是请记住,每个软件都需要维护……
所以我的建议是:在真正需要接口之前不要使用它们。(使用Visual Studio,你可以在2秒内从现有的类中提取一个接口——所以不要着急。)
话虽如此,你什么时候需要创建一个接口呢?
当我重构一个突然需要处理两个或多个类似类的方法时,我就会这样做。然后创建一个接口,将该接口分配给两个(或多个)类似的类,并更改方法参数类型(将类类型替换为接口类型)。
它是有效的:o)
一个例外:当我模拟对象时,接口更容易使用。我经常为此创建接口。
PS:当我写“接口”时,我的意思是:“任何基类的接口”,包括纯接口类。请注意,抽象类通常比纯接口更好,因为您可以向它们添加逻辑。
此致,Sylvain。
如果浏览. net Framework程序集并深入到任何标准对象的基类中,您将注意到许多接口(名为ISomeName的成员)。
Interfaces are basically for implementing frameworks, large or small. I felt the same way about interfaces until I wanted to write a framework of my own. I also found that understanding interfaces helped me learn frameworks much more rapidly. The moment that you want to write a more elegant solution for just about anything, you will find that an interface makes a lot of sense. It's like a method of letting a class put on the appropriate clothes for the job. More importantly, interfaces allow systems to become much more self-documenting, because complex objects become less complex when the class implements interfaces, which helps to categorize its functionality.
类在希望能够显式或隐式地参与框架时实现接口。例如,IDisposable是一个公共接口,它为流行且有用的Dispose()方法提供方法签名。在框架中,您或其他开发人员需要知道的关于类的所有信息是,如果它实现了IDisposable,那么您就知道((IDisposable)myObject). dispose()可用于清理目的。
经典示例:在没有实现IDisposable接口的情况下,你不能在c#中使用"using()"关键字构造,因为它要求任何指定为参数的对象都可以隐式转换为IDisposable。
复杂的例子:
一个更复杂的例子是System.ComponentModel.Component类。这个类同时实现了IDisposable和IComponent。大多数(如果不是全部的话)具有与之关联的可视化设计器的. net对象实现了IComponent,以便IDE能够与组件交互。
CONCLUSION:
As you become more familiar with the .NET Framework, the first thing you will do when encountering a new class in the Object Browser or within the .NET Reflector (free) tool (http://www.red-gate.com/products/reflector/) is to check to see which class it inherits from and also the interfaces that it implements. .NET Reflector is even better than the Object Browser because it lets you see the Derived classes as well. That allows you to learn about all objects that derive from a particular class, thereby potentially learning about framework functionality that you did not know existed. This is particularly significant when updated or new namespaces are added to the .NET Framework.
把接口想象成一个契约。这是一种说法,“这些类应该遵循这些规则。”
所以在IAnimal的例子中,它是一种说,“我必须能够在实现IAnimal的类上调用Run, Walk等。”
为什么这个有用?您可能希望构建一个函数,该函数依赖于必须能够在对象上调用Run和Walk这一事实。你可以有以下内容:
public void RunThenWalk(Monkey m) {
m.Run();
m.Walk();
}
public void RunThenWalk(Dog d) {
d.Run();
d.Walk();
}
... 对所有你知道能跑能走的物体重复这一步骤。然而,在你的IAnimal接口中,你可以像下面这样定义函数:
public void RunThenWalk(IAnimal a) {
a.Run();
a.Walk();
}
通过根据接口编程,您实际上是信任类来实现接口的目的。所以在我们的例子中,想法是“我不在乎他们怎么跑和走,只要他们能跑和走。”只要他们履行协议,我的RunThenWalk就有效。它在不了解任何其他课程的情况下运行得很好。”
在这个相关的问题上也有很好的讨论。
它解决了一个具体的问题:
你有a b c d四种不同类型。在你的代码中,你可以这样写:
a.Process();
b.Process();
c.Process();
d.Process();
为什么不让他们实现IProcessable呢
List<IProcessable> list;
foreach(IProcessable p in list)
p.Process();
当你添加50种类型的类,它们都做同样的事情时,这种伸缩性会更好。
另一个具体问题是:
你有没有看过System.Linq.Enumerable?它定义了大量的扩展方法,可以对实现IEnumerable的任何类型进行操作。因为任何实现IEnumerable的东西基本上都在说“我支持无序foreach类型模式中的迭代”,所以你可以为任何可枚举类型定义复杂的行为(Count、Max、Where、Select等)。