我曾多次看到有人提到这一点,但我不清楚这是什么意思。你什么时候,为什么要这么做?

我知道接口是做什么的,但我不清楚这一点的事实使我认为我错过了正确使用它们。

如果你要这样做

IInterface classRef = new ObjectWhatever()

你可以使用任何实现IInterface的类吗?你什么时候需要这样做?我能想到的唯一一件事是,如果你有一个方法,你不确定什么对象将被传递,除了它实现IInterface。我不知道你需要多久做一次。

另外,如何编写一个方法来接受实现接口的对象呢?这可能吗?


当前回答

我坚信困难的问题应该用现实世界中简单的答案来解释。在软件设计领域,这是非常重要的。

看看你家里、学校、教堂的任何一扇门……任何建筑。

想象一下,有些门的底部有危险(所以你必须鞠躬才能与开门或关门的门互动),

或者其他人只能坐在左上角(所以,一些侏儒、残疾人或凯文·哈特不会觉得这种门很有趣,也不会觉得它很好用)。

所以设计是关键,创建程序让其他人可以开发/使用它。

接口的作用是让大型项目中的初级/高级开发人员更容易工作,这样每个人都知道自己在做什么,而不需要别人的帮助,这样你就可以尽可能顺利地工作(理论上)。


[1]:如何?通过揭示价值的形态。所以,你不需要文档,因为代码本身是不言自明的(棒极了)。


这个答案并不是针对特定语言的,而是概念驱动的(毕竟,人类是通过编写代码来创建工具的)。

其他回答

Using interfaces is a key factor in making your code easily testable in addition to removing unnecessary couplings between your classes. By creating an interface that defines the operations on your class, you allow classes that want to use that functionality the ability to use it without depending on your implementing class directly. If later on you decide to change and use a different implementation, you need only change the part of the code where the implementation is instantiated. The rest of the code need not change because it depends on the interface, not the implementing class.

This is very useful in creating unit tests. In the class under test you have it depend on the interface and inject an instance of the interface into the class (or a factory that allows it to build instances of the interface as needed) via the constructor or a property settor. The class uses the provided (or created) interface in its methods. When you go to write your tests, you can mock or fake the interface and provide an interface that responds with data configured in your unit test. You can do this because your class under test deals only with the interface, not your concrete implementation. Any class implementing the interface, including your mock or fake class, will do.

编辑:下面是一篇文章的链接,其中Erich Gamma讨论了他的引用,“面向接口编程,而不是面向实现编程。”

http://www.artima.com/lejava/articles/designprinciples.html

因此,为了做到这一点,接口的优点是我可以将方法的调用与任何特定的类分开。而是创建接口的实例,其中的实现来自我选择的实现该接口的任何类。因此,允许我拥有许多类,它们具有相似但略有不同的功能,并且在某些情况下(与接口的意图相关的情况)并不关心它是哪个对象。

例如,我可以有一个移动界面。一个方法可以让一些东西“移动”,任何实现移动接口的对象(Person, Car, Cat)都可以被传递进来并被告知移动。如果每个方法都不知道类的类型,那么它就是类。

问:——……“你能使用任何实现接口的类吗?” A:是的。 问:——……“你什么时候需要这样做?” 答:-每次你都需要一个实现接口的类。

注意:我们不能实例化一个没有被类实现的接口- True。

为什么? 因为接口只有方法原型,没有定义(只有函数名,没有它们的逻辑)

AnIntf anInst = new class(); //我们可以这样做,只有当类实现AnIntf。 // anInst将有类引用。


注意:现在我们可以理解如果Bclass和Cclass实现相同的Dintf会发生什么。

Dintf bInst = new Bclass();  
// now we could call all Dintf functions implemented (defined) in Bclass.

Dintf cInst = new Cclass();  
// now we could call all Dintf functions implemented (defined) in Cclass.

我们拥有:相同的接口原型(接口中的函数名),调用不同的实现。

参考书目: 原型——维基百科

此外,我在这里看到了很多很好的解释性答案,所以我想在这里给出我的观点,包括一些我在使用这种方法时注意到的额外信息。

单元测试

在过去的两年里,我写了一个业余项目,但我没有为它写单元测试。在写了大约50K行代码后,我发现编写单元测试是非常必要的。 我没有使用接口(或者很少使用)……当我做第一个单元测试时,我发现它很复杂。为什么?

因为我必须创建大量的类实例,用作类变量和/或参数的输入。所以测试看起来更像集成测试(必须制作一个完整的类“框架”,因为所有的类都捆绑在一起)。

界面恐惧 所以我决定使用接口。我担心的是我必须在所有地方(在所有使用的类中)多次实现所有功能。在某种程度上,这是正确的,然而,通过使用继承,它可以减少很多。

接口和继承的组合 我发现这个组合很好用。我举一个非常简单的例子。

public interface IPricable
{
    int Price { get; }
}

public interface ICar : IPricable

public abstract class Article
{
    public int Price { get { return ... } }
}

public class Car : Article, ICar
{
    // Price does not need to be defined here
}

这样就不需要复制代码,同时仍然有使用汽车作为接口(ICar)的好处。

在Java中,这些具体类都实现了CharSequence接口:

神健壮健壮健壮健壮

除了Object之外,这些具体的类没有共同的父类,因此它们之间没有任何联系,除了它们各自都与字符数组有关,表示或操作这些字符。例如,String对象实例化后,String的字符不能被更改,而StringBuffer或StringBuilder的字符可以被编辑。

然而,这些类中的每一个都能够适当地实现CharSequence接口方法:

char charAt(int index)
int length()
CharSequence subSequence(int start, int end)
String toString()

在某些情况下,曾经接受String的Java类库类已经修改为现在接受CharSequence接口。因此,如果你有一个StringBuilder实例,而不是提取一个String对象(这意味着实例化一个新的对象实例),它可以在实现CharSequence接口时直接传递StringBuilder本身。

某些类实现的Appendable接口对于任何可以将字符追加到底层具体类对象实例的实例的情况都具有大致相同的好处。所有这些具体类都实现了Appendable接口:

BufferedWriter, CharArrayWriter, CharBuffer, FileWriter, FilterWriter, LogStream, OutputStreamWriter, PipedWriter, PrintStream, PrintWriter, StringBuffer, StringBuilder, StringWriter, Writer