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

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

接口:

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

抽象类:

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

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

另请参阅:

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


当前回答

其他一些区别:

抽象类可以有静态方法、财产、字段等,而操作符和接口则不能。强制转换运算符允许向抽象类强制转换,但不允许向接口强制转换。

所以,即使抽象类从未实现(通过它的静态成员),也可以单独使用抽象类,并且不能以任何方式单独使用接口。

其他回答

从编码角度

如果抽象类只有抽象方法,则接口可以替换抽象类。否则,将抽象类更改为接口意味着您将失去继承提供的代码重用性。

从设计角度

如果它是“Is a”关系,并且您需要一个子集或所有功能,请将其保留为抽象类。如果是“应该做”的关系,请将其保留为界面。

决定你需要什么:只是策略执行,或者代码重用和策略。

接口:如果您希望在组件上暗示规则,则应使用该接口彼此相关的

赞成的意见:

允许多重继承通过不公开上下文中使用的确切类型的对象来提供抽象通过合同的特定签名提供一致性

欺骗:

必须执行所有定义的合同不能有变量或委托一旦定义,就不能在不破坏所有类的情况下进行更改

抽象类:应用于希望对彼此相关的组件具有一些基本或默认行为或实现的情况

赞成的意见:

比接口更快在实施中具有灵活性(您可以完全或部分实施)可以在不破坏派生类的情况下轻松更改

欺骗:

无法实例化不支持多重继承

如果您认为java是OOP语言来回答这个问题,那么Java8的发布会导致上述答案中的一些内容过时。现在,java接口可以具有具有具体实现的默认方法。

Oracle网站提供了接口和抽象类之间的关键区别。

如果出现以下情况,请考虑使用抽象类:

您希望在几个密切相关的类之间共享代码。您希望扩展抽象类的类具有许多公共方法或字段,或者需要公共以外的访问修饰符(如protected和private)。您要声明非静态或非final字段。

如果出现以下情况,请考虑使用接口:

您希望不相关的类实现您的接口。例如,许多不相关的对象可以实现Serializable接口。您希望指定特定数据类型的行为,但不关心谁实现了它的行为。您希望利用类型的多重继承。

简单来说,我想使用

接口:通过多个不相关的对象实现合同

抽象类:在多个相关对象之间实现相同或不同的行为

看看代码示例,以清楚的方式理解事情:我应该如何解释接口和抽象类之间的区别?

还有一些其他的区别-

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

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

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

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

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

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

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