在我的开发学习中,我觉得我必须学习更多关于接口的知识。

我经常读到它们,但我似乎无法理解它们。

我读过这样的例子:动物基类,IAnimal接口的东西,如“Walk”,“Run”,“GetLegs”等-但我从来没有工作过,觉得“嘿,我应该在这里使用接口!”

我错过了什么?为什么这个概念对我来说这么难理解!我只是害怕这样一个事实,我可能从来没有意识到一个具体的需要-主要是由于一些缺失的理解他们!这让我觉得我作为一名开发人员缺少了一些东西!如果有人有过这样的经历,并取得了突破,我会很感激一些关于如何理解这个概念的建议。谢谢你!


当前回答

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这样更像软件的东西,这样的类比就更接近你在实际程序中看到的情况了。

其他回答

作为一个。net开发人员,你完全有可能一辈子都不编写自己的接口。毕竟,没有它们,我们也活了几十年,我们的语言仍然是图灵完备的。

我不能告诉你为什么你需要接口,但我可以给你一个我们在当前项目中使用它们的列表:

在我们的插件模型中,我们通过接口加载插件,并将该接口提供给插件编写者以使其遵循。 在我们的机间消息传递系统中,消息类都实现了一个特定的接口,并使用该接口“解包装”。 我们的配置管理系统定义了一个用于设置和检索配置设置的接口。 我们使用一个接口来避免讨厌的循环引用问题。(如果没有必要,就不要这样做。)

我想如果有一个规则,那就是当你想在一个is-a关系中对几个类进行分组,但你不想在基类中提供任何实现时使用接口。

当您希望定义对象可以显示的行为时,通常会使用接口。

在. net世界中,一个很好的例子是IDisposable接口,它用于任何使用必须手动释放的系统资源的Microsoft类。它要求实现它的类具有Dispose()方法。

Dispose()方法也被VB的using语言构造调用。NET和c#,只适用于IDisposables)

请记住,您可以通过使用诸如TypeOf…之类的构造来检查对象是否实现了特定的接口。Is (VB.NET), Is (c#), instanceof (Java),等等…

当您成为库开发人员(为其他编码员编写代码的人)时,接口将变得很明显。我们中的大多数人都是从应用程序开发人员开始的,我们使用现有的api和编程库。

同样的,接口是一种契约,还没有人提到接口是一种使代码的某些部分稳定的好方法。当它是一个团队项目时(或者当您正在开发其他开发人员使用的代码时),这尤其有用。所以,这里有一个具体的场景:

当您在团队中开发代码时,其他人可能会使用您编写的代码。当他们为你的(稳定的)接口编写代码时,他们会非常高兴,而当你可以自由地改变你的实现(隐藏在接口后面)而不破坏你团队的代码时,你也会非常高兴。它是信息隐藏的一种变体(接口是公开的,实现对客户端程序员隐藏)。阅读更多关于受保护的变种。

另请参阅有关接口编码的相关问题。

一个代码示例(结合了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的抽象基类)。但是考虑到您需要使用第三方记录器,它迫使您使用基类(假设它公开了您需要使用的受保护的方法)。由于语言不支持多重继承,您将无法使用抽象基类方法。

底线是:尽可能使用接口来获得代码的额外灵活性。您的实现不那么受约束,因此它能更好地适应变化。

使用接口有很多目的。

Use in polymorphic behavior. Where you want to call specific methods of a child class with an inteface having a reference to the child class. Having a contract with classes to implement all of the methods where it is necessary, like most common use is with COM objects , where a wrapper class is generated on a DLL which inherits the interface; these methods are called behind the scenes, and you just need to implement them but with the same structure as defined in the COM DLL which you can only know through the interface that they expose. To reduce memory usage by loading specific methods in a class. Like if you have three business objects and they are implemented in a single class, you can use three interfaces.

例如IUser, IOrder, IOrderItem

public interface IUser()
{

void AddUser(string name ,string fname);

}

// Same for IOrder and IOrderItem
//


public class  BusinessLayer: IUser, IOrder, IOrderItem

{    
    public void AddUser(string name ,string fname)
    {
        // Do stuffs here.
    }

    // All methods from all interfaces must be implemented.

}

如果你只想添加一个用户,可以这样做:

IUser user = new (IUser)BusinessLayer();

// It will load  all methods into memory which are declared in the IUser interface.

user.AddUser();