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

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

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

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


当前回答

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

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

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

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

其他回答

假设你想要模拟当你试图睡觉时可能发生的烦恼。

接口前的模型

class Mosquito {
    void flyAroundYourHead(){}
}

class Neighbour{
    void startScreaming(){}
}

class LampJustOutsideYourWindow(){
    void shineJustThroughYourWindow() {}
}

正如你清楚地看到的,当你试图睡觉时,许多“事情”都可能令人讨厌。

使用没有接口的类

但是在使用这些类时,我们遇到了一个问题。他们毫无共同之处。您必须分别调用每个方法。

class TestAnnoyingThings{
    void testAnnoyingThinks(Mosquito mosquito, Neighbour neighbour, LampJustOutsideYourWindow lamp){
         if(mosquito != null){
             mosquito.flyAroundYourHead();
         }
         if(neighbour!= null){
             neighbour.startScreaming();
         }
         if(lamp!= null){
             lamp.shineJustThroughYourWindow();
         }
    }
}

带有接口的模型

为了克服这个问题,我们可以引入一个iterface

interface Annoying{
   public void annoy();

}

并在类中实现它

class Mosquito implements Annoying {
    void flyAroundYourHead(){}

    void annoy(){
        flyAroundYourHead();
    }
}

class Neighbour implements Annoying{
    void startScreaming(){}

    void annoy(){
        startScreaming();
    }
}

class LampJustOutsideYourWindow implements Annoying{
    void shineJustThroughYourWindow() {}

    void annoy(){
        shineJustThroughYourWindow();
    }
}

接口使用

这将使这些类的使用更容易

class TestAnnoyingThings{
    void testAnnoyingThinks(Annoying annoying){
        annoying.annoy();
    }
}

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,你可以只阅读本章的开头,主要是一些概念。

使用接口有很多目的。

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();

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

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

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

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

把接口想象成一个契约。这是一种说法,“这些类应该遵循这些规则。”

所以在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就有效。它在不了解任何其他课程的情况下运行得很好。”

在这个相关的问题上也有很好的讨论。