“按接口编程”是什么意思?

920
我在几次提到过这个,但不清楚它是什么意思。你什么时候和为什么要这样做?
我知道接口是做什么的,但因为我不太清楚这一点,所以我认为我可能没有正确地使用它们。
这只是为了让你能够执行以下操作吗?
IInterface classRef = new ObjectWhatever()

你可以使用任何实现了 IInterface 接口的类?那么什么情况下需要这样做呢?我所能想到的唯一情形是,当你有一个方法并且不确定将传递哪个对象,除非它实现了 IInterface 接口。我认为这种情况并不经常出现。

另外,你如何编写一个接收实现某个接口的对象作为参数的方法呢?这是可能的吗?


4
如果你记得的话,并且你的程序需要优化,在编译之前,你可能希望交换接口声明与实际实现。因为使用接口会增加间接性,从而影响性能。但是,建议将代码编写为基于接口编程的形式进行分发。 - Ande Turner
25
@Ande Turner:那是很糟糕的建议。1)“你的程序需要是最优的”不是替换接口的好理由!然后你说“通过接口编写代码…”,所以你建议在满足要求(1)的情况下发布次优代码吗?!?Translated: @Ande Turner: 那是差劲的建议。1)“你的程序需要是最优的”不是替换接口的好理由!然后你说“通过接口编写代码…”,所以你建议在满足需求(1)的情况下发布次优代码吗?!? - Mitch Wheat
82
这里大部分答案都不太正确。它根本不意味着“使用interface关键字”。接口是使用某物的规范,与合同(请查阅)相同。除此之外的是实现,即如何履行该合同。只针对方法/类型的保证进行编程,以便在方法/类型以遵守合同的方式发生变化时,不会破坏使用它的代码。 - jyoungdev
2
@apollodude217,这实际上是整个页面上最好的答案。至少对于标题中的问题来说是这样,因为这里至少有3个非常不同的问题... - Andrew Spencer
7
这类问题的根本问题在于它假设“按照接口编程”意味着“将所有内容都封装在抽象接口中”,如果你考虑到这个术语早于Java风格的抽象接口概念,那么这种想法就是愚蠢的。 - Jonathan Allen
显示剩余9条评论
33个回答

0

我坚信,难题应该用易于理解的现实答案来解释。在软件设计领域,这非常重要。

看看你家、学校、教堂或任何建筑物中的任何一扇门。

想象一些门底部放置了危险物品(因此您必须鞠躬才能与门互动,即打开或关闭它),

或者其他门只在左上角(因此,某些侏儒、残疾人或凯文·哈特将不会发现这样的门很有趣和可用)。

因此,“设计”是关键词,创建程序以便其他“人类”可以“开发/使用它”。

接口所做的就是为其他初级/高级开发人员提供便利,跨巨大项目[1],这样每个人都知道他们正在做什么,并且尽可能少地从其他人那里获得帮助,以便您可以尽可能顺畅地工作(理论上)。


[1]:如何做到呢?通过暴露值的形状。因此,您不需要文档,因为代码本身是自说明的(非常棒)。


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


一般情况下,接口的使用非常好且(抽象)解释得很清楚。 - Lars Hansen

0

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

单元测试

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


-1

这里有一个简单的例子,用来说明当你编写一个航班预订系统时。

//This interface is very flexible and abstract
    addPassenger(Plane seat, Ticket ticket); 

//Boeing is implementation of Plane
    addPassenger(Boeing747 seat, EconomyTicket ticket); 
    addPassenger(Cessna, BusinessClass ticket);


    addPassenger(J15, E87687); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接