在我的开发学习中,我觉得我必须学习更多关于接口的知识。
我经常读到它们,但我似乎无法理解它们。
我读过这样的例子:动物基类,IAnimal接口的东西,如“Walk”,“Run”,“GetLegs”等-但我从来没有工作过,觉得“嘿,我应该在这里使用接口!”
我错过了什么?为什么这个概念对我来说这么难理解!我只是害怕这样一个事实,我可能从来没有意识到一个具体的需要-主要是由于一些缺失的理解他们!这让我觉得我作为一名开发人员缺少了一些东西!如果有人有过这样的经历,并取得了突破,我会很感激一些关于如何理解这个概念的建议。谢谢你!
一个代码示例(结合了Andrew的代码和我的额外的关于“接口的目的是什么”的代码),也说明了为什么在不支持多重继承的语言(c#和java)上接口而不是抽象类:
interface ILogger
{
void Log();
}
class FileLogger : ILogger
{
public void Log() { }
}
class DataBaseLogger : ILogger
{
public void Log() { }
}
public class MySpecialLogger : SpecialLoggerBase, ILogger
{
public void Log() { }
}
注意,FileLogger和DataBaseLogger不需要接口(可以是Logger的抽象基类)。但是考虑到您需要使用第三方记录器,它迫使您使用基类(假设它公开了您需要使用的受保护的方法)。由于语言不支持多重继承,您将无法使用抽象基类方法。
底线是:尽可能使用接口来获得代码的额外灵活性。您的实现不那么受约束,因此它能更好地适应变化。
与任何为系统增加灵活性的编程技术一样,接口也增加了一定程度的复杂性。它们通常都很好,而且你可以在任何地方使用它(你可以为你的所有类创建一个接口)——但是这样做,你会创建一个更复杂的系统,更难维护。
像往常一样,这里有一个权衡:灵活性胜过可维护性。哪个更重要?没有答案——这取决于项目本身。但是请记住,每个软件都需要维护……
所以我的建议是:在真正需要接口之前不要使用它们。(使用Visual Studio,你可以在2秒内从现有的类中提取一个接口——所以不要着急。)
话虽如此,你什么时候需要创建一个接口呢?
当我重构一个突然需要处理两个或多个类似类的方法时,我就会这样做。然后创建一个接口,将该接口分配给两个(或多个)类似的类,并更改方法参数类型(将类类型替换为接口类型)。
它是有效的:o)
一个例外:当我模拟对象时,接口更容易使用。我经常为此创建接口。
PS:当我写“接口”时,我的意思是:“任何基类的接口”,包括纯接口类。请注意,抽象类通常比纯接口更好,因为您可以向它们添加逻辑。
此致,Sylvain。
把接口想象成一个契约。这是一种说法,“这些类应该遵循这些规则。”
所以在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就有效。它在不了解任何其他课程的情况下运行得很好。”
在这个相关的问题上也有很好的讨论。
I like Jimmy's answer a lot, but I feel I need to add something to it. The key to the whole thing is the "able" in IProcessable . It indicates a capability (or property, but meaning "intrinsic quality", not in the sense of C# properties) of the object that implements the interface. IAnimal is probably not a good example for an interface, but IWalkable might be a good interface to have if your system has many things that can walk. You might have classes derived from Animal such as Dog, Cow, Fish, Snake. The first two would probably implement IWalkable, the latter two don't walk, so they wouldn't. Now you ask "why not just have another superclass, WalkingAnimal, that Dog and Cow derive from?". The answer is when you have something completely outside the inheritance tree that also can walk, such as a robot. Robot would implement IWalkable, but probably wouldn't derive from Animal. If you want a list of things that can walk, you type it as IWalkable and you can put all walking animals plus robots in the list.
现在,将IWalkable替换为IPersistable这样更像软件的东西,这样的类比就更接近你在实际程序中看到的情况了。