我最近接受了两次电话采访,被问及接口类和抽象类之间的区别。我已经解释了我能想到的每一个方面,但似乎他们在等我提一些具体的事情,我不知道是什么。

根据我的经验,我认为以下是正确的。如果我遗漏了一个要点,请告诉我。

接口:

接口中声明的每个方法都必须在子类中实现。接口中只能存在事件、委托、财产(C#)和方法。一个类可以实现多个接口。

抽象类:

子类只能实现抽象方法。抽象类可以具有具有实现的普通方法。除了事件、委托、财产和方法之外,抽象类还可以有类变量。由于C#中不存在多重继承,一个类只能实现一个抽象类。

在这之后,面试官提出了一个问题:“如果你有一个只有抽象方法的抽象类呢?这和接口有什么不同?”我不知道答案,但我认为这是上面提到的继承,对吧?另一位面试官问我,“如果你在接口中有一个公共变量,那会和抽象类中有什么不同?”我坚持认为你不能在接口中使用公共变量。我不知道他想听什么,但他也不满意。

另请参阅:

何时使用接口而不是抽象类,反之亦然接口与抽象类如何决定使用抽象类和接口?接口和抽象类之间的区别是什么?


当前回答

还有一些其他的区别-

接口不能有任何具体的实现。抽象基类可以。这允许您在那里提供具体的实现。这可以允许抽象基类实际上提供更严格的契约,而接口实际上只描述如何使用类。(抽象基类可以具有定义行为的非虚拟成员,这给了基类作者更多的控制权。)

一个类上可以实现多个接口。类只能从单个抽象基类派生。这允许使用接口的多态层次结构,但不允许抽象基类。这也允许使用接口进行伪多重继承。

抽象基类可以在v2+中修改,而不破坏API。对接口的更改正在破坏更改。

[C#/.NET特定]接口与抽象基类不同,可以应用于值类型(结构)。结构不能从抽象基类继承。这允许将行为契约/使用指南应用于价值类型。

其他回答

After all that, the interviewer came up with the question "What if you had an 
Abstract class with only abstract methods? How would that be different
from an interface?" 

文档明确指出,如果抽象类只包含抽象方法声明,则应将其声明为接口。

An another interviewer asked me what if you had a Public variable inside
the interface, how would that be different than in Abstract Class?

默认情况下,接口中的变量是公共静态变量和最终变量。问题的框架可以是,如果抽象类中的所有变量都是公共的呢?与接口中的变量不同,它们仍然可以是非静态和非最终的。

最后,我想对上面提到的内容再补充一点——抽象类仍然是类,属于单个继承树,而接口可以存在于多个继承中。

除了将抽象类与接口进行比较之外,将抽象类和具体类进行比较是有意义的。

使用抽象类就像使用具体类一样,除非您不希望/无法在没有扩展的情况下实例化它们。让你不想/不能实现抽象方法的方法。

如果你喜欢类比,就把chrome当作一个抽象类(你不能把它当作浏览器,所以它不能被实例化),把chrome和opera当作从chrome派生的具体类,把浏览器插件结构当作接口。

我认为他们不喜欢你的回应,因为你给出的是技术上的差异,而不是设计上的差异。对我来说,这个问题就像一个巨魔问题。事实上,接口和抽象类有着完全不同的性质,所以你无法真正比较它们。我将向您介绍接口的作用和抽象类的作用。

接口:用于确保契约和类之间的低耦合,以获得更可维护、可扩展和可测试的应用程序。

抽象类:仅用于在具有相同响应性的类之间分解某些代码。请注意,这是为什么多重继承在OOP中是一件坏事的主要原因,因为类不应该处理许多响应(而是使用组合)。

因此,接口具有真正的体系结构角色,而抽象类几乎只是实现的一个细节(当然,如果正确使用的话)。

打个比方吧:当我在空军时,我参加了飞行员培训,成为了一名美国空军飞行员。当时我没有资格驾驶任何飞机,必须参加飞机类型的训练。一旦我获得资格,我就是一名飞行员(抽象类)和一名C-141飞行员(具体类)。在我的一项任务中,我被赋予了一项额外的职责:安全员。现在我仍然是一名飞行员和C-141飞行员,但我也履行了安全员的职责(可以说,我执行了ISafetyOfficer)。飞行员不需要是安全员,其他人也可以这样做。

所有美国空军飞行员都必须遵守某些空军规定,所有C-141(或F-16或T-38)飞行员都是“美国空军飞行员”。任何人都可以成为安全员。因此,总结如下:

Pilot:抽象类C-141试验:混凝土等级ISafety Officer:接口

补充说明:这是一个类比,以帮助解释概念,而不是编码建议。看到下面的各种评论,讨论很有趣。

对于.Net,

你对第二位面试官的回答也是对第一位的回答。。。抽象类可以有实现,AND状态,接口不能。。。

编辑:另一方面,我甚至不会使用短语“subclass”(或“继承”短语)来描述“定义为实现”接口的类。对我来说,接口是一个合约的定义,如果类被定义为“实现”该接口,那么它必须遵守该定义。它没有继承任何东西。。。你必须自己明确地添加所有内容。