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

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

如果你要这样做

IInterface classRef = new ObjectWhatever()

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

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


当前回答

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

单元测试

在过去的两年里,我写了一个业余项目,但我没有为它写单元测试。在写了大约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)的好处。

其他回答

编程到接口允许无缝地改变由接口定义的契约的实现。它允许契约和特定实现之间的松耦合。

IInterface classRef = new ObjectWhatever() 你可以使用任何实现IInterface的类吗?你什么时候需要这样做?

看看这个SE问题的好例子。

为什么应该首选Java类的接口?

使用接口会影响性能吗? 如果有,多少钱?

是的。它将在几秒内产生轻微的性能开销。但是如果您的应用程序需要动态地更改接口的实现,则不必担心性能影响。

如何避免这种情况而不需要维护两段代码呢?

如果您的应用程序需要多个接口实现,不要试图避免它们。在接口与某个特定实现缺乏紧密耦合的情况下,您可能必须部署补丁以将一个实现更改为另一个实现。

一个好的用例:Strategy模式的实现:

策略模式的真实例子

If you program in Java, JDBC is a good example. JDBC defines a set of interfaces but says nothing about the implementation. Your applications can be written against this set of interfaces. In theory, you pick some JDBC driver and your application would just work. If you discover there's a faster or "better" or cheaper JDBC driver or for whatever reason, you can again in theory re-configure your property file, and without having to make any change in your application, your application would still work.

为了补充现有的帖子,当开发人员同时在不同的组件上工作时,有时对接口进行编码有助于大型项目。您所需要做的就是预先定义接口并为它们编写代码,而其他开发人员则为您正在实现的接口编写代码。

面向接口编程非常棒,它促进了松耦合。正如@lassevk提到的,控制反转是一个很好的应用。

此外,研究SOLID原则。这是一个系列视频

它通过硬编码(强耦合示例),然后查看接口,最后进展到IoC/DI工具(NInject)。

假设你有一个名为“Zebra”的产品,可以通过插件进行扩展。它通过在某个目录中搜索dll来查找插件。它加载所有这些dll,并使用反射来查找实现IZebraPlugin的任何类,然后调用该接口的方法来与插件通信。

这使得它完全独立于任何特定的插件类——它不关心类是什么。它只关心它们是否满足接口规范。

接口是这样定义可扩展性点的一种方式。与接口对话的代码是松散耦合的——事实上,它与任何其他特定的代码根本不耦合。它可以与多年后由从未见过原始开发人员的人编写的插件进行互操作。

你可以使用一个带有虚函数的基类——所有的插件都是从基类派生的。但这有很大的限制,因为一个类只能有一个基类,而它可以实现任意数量的接口。