【问题标题】:What is the difference between an interface and abstract class?接口和抽象类有什么区别?
【发布时间】:2010-12-27 03:40:08
【问题描述】:

接口和抽象类到底有什么区别?

【问题讨论】:

  • 这是一个非常常见的面试问题。令人惊讶的是,与其他事物相比,抽象类很少用于解决方案。你的问题帮助了我 Safraz。
  • 这个问题也可能有助于理解接口的概念stackoverflow.com/q/8531292/1055241
  • 我已经从这个问题中删除了 PHP 标记,因为几乎没有一个答案是特定于语言的,而且问题本身也不是特定于语言的。
  • 在过去的 C++ 中,接口是一个纯抽象基类,所有方法实现 = 0。如果单个方法不 = 0,那么它有一个实现,而抽象基类没有不再纯粹,不再是界面。我认为当多重继承仅使用纯抽象基时,VMT 的间接性较少,但我不记得它们长什么样了,太长了。

标签: oop interface abstract-class


【解决方案1】:

php.net上的抽象类和接口简单有效的解释:

接口就像一个协议。它不指定对象的行为;它指定您的代码如何告诉该对象采取行动。接口类似于英语:定义接口定义了您的代码如何与实现该接口的任何对象进行通信。

接口始终是协议或承诺。当一个类说“我实现接口 Y”时,它是在说“我保证拥有与任何具有接口 Y 的对象相同的公共方法”。

另一方面,抽象类就像一个部分构建的类。它很像一个需要填写空白的文档。它可能使用英语,但这并不像某些文档已经写好这一事实那么重要。

抽象类是另一个对象的基础。当一个类说“我扩展抽象类 Y”时,它是在说“我使用了一些已经在另一个名为 Y 的类中定义的方法或属性”。

所以,请考虑以下 PHP:

<?php
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.

class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>

如果你分发一个类供其他人使用,你会让你的类实现一个特定的接口。接口是为您的类提供一组特定公共方法的协议。

如果您(或其他人)编写了一个已经编写了一些您想在新类中使用的方法的类,那么您将让您的类扩展一个抽象类。

这些概念虽然很容易混淆,但具体不同且截然不同。出于所有意图和目的,如果您是任何类的唯一用户,则无需实现接口。

【讨论】:

    【解决方案2】:

    我们在接口和抽象类之间有各种结构/语法差异。还有一些区别是

    [1] 基于场景的差异

    抽象类用于我们希望限制用户创建父类对象的场景,我们相信未来会添加更多的抽象方法。

    当我们确定没有更多抽象方法可以提供时,必须使用接口。然后只发布一个接口。

    [2] 概念差异

    “我们将来是否需要提供更多抽象方法”如果是,则将其设为抽象类,如果否,则将其设为接口。

    (在 java 1.7 之前最合适和有效)

    【讨论】:

      【解决方案3】:

      通常抽象类用于核心,而接口用于附加外围设备。

      当你想为车辆创建基本类型时,你应该使用抽象类,但是如果你想添加一些不属于车辆基本概念的功能或属性,你应该使用接口,例如你想添加“ToJSON( )”函数。

      接口具有广泛的抽象而不是抽象类。 你可以在传递参数中看到这一点。看这个例子:

      如果您使用车辆作为参数,则可以使用其派生类型之一(公共汽车或汽车-相同类别-仅车辆类别)。 但是当你使用 IMoveable 接口作为参数时,你有更多的选择。

      【讨论】:

        【解决方案4】:

        在实用性方面(JAVA),抽象类和接口之间的主要区别是 抽象类可以保持状态。 除了保持状态,我们还可以通过接口实现休息操作。

        【讨论】:

          【解决方案5】:

          我迟到了 10 年,但我想尝试任何方式。几天前写了一篇关于相同的帖子。想把它贴在这里。

          tl;博士;当您看到“Is A”关系时,请使用继承/抽象类。当你看到“有”关系时,创建成员变量。当您看到“依赖于外部提供者”时,实现(而不是继承)一个接口。

          面试题:接口和抽象类有什么区别?你如何决定何时使用什么? 我大多得到以下一个或全部答案: 答案1:不能创建抽象类和接口的对象。

          ZK(这是我的首字母缩写):你不能创建任何一个对象。所以这没有区别。这是接口和抽象类之间的相似之处。柜台 问题:为什么不能创建抽象类或接口的对象?

          答案 2: 抽象类可以有一个函数体作为部分/默认实现。

          ZK: 反问:所以如果我把它改成一个纯抽象类,把所有的虚函数都标记为抽象并且不为任何虚函数提供默认实现。那会使抽象类和接口相同吗?之后它们可以互换使用吗?

          答案 3:接口允许多重继承,而抽象类不允许。

          ZK: 反问:你真的从接口继承吗?还是您只是实现一个接口并从抽象类继承?实现和继承有什么区别? 这些反题让候选人望而却步,让大多数人摸不着头脑,或者直接跳到下一个问题。这让我觉得人们在面向对象编程的这些基本构建块方面需要帮助。 原始问题和所有反问题的答案都可以在英语和 UML 中找到。 您必须至少了解以下内容才能更好地理解这两个构造。

          普通名词:普通名词是对同一类或同类事物“共同”给予的名称。例如水果、动物、城市、汽车等。

          专有名词:专有名词是物体、地点或事物的名称。 Apple、Cat、New York、Honda Accord 等

          汽车是普通名词。而本田雅阁是一个专有名词,也可能是一个复合专有名词,一个由两个名词组成的专有名词。

          来到 UML 部分。您应该熟悉以下关系:

          • 是阿
          • 有一个
          • 用途

          让我们考虑以下两个句子。 - 本田雅阁是汽车吗? - 本田雅阁有车吗?

          哪一个听起来是正确的?简单的英语和理解力。 HondaAccord 和 Cars 共享“Is A”关系。本田雅阁没有汽车。这是辆车。本田雅阁“有一个”音乐播放器。

          当两个实体共享“Is A”关系时,它更适合继承。并且有一个关系是创建成员变量的更好候选者。 有了这个,我们的代码看起来像这样:

          abstract class Car
          {
             string color;
             int speed;
          }
          class HondaAccord : Car
          {
             MusicPlayer musicPlayer;
          }
          

          现在本田不生产音乐播放器。或者至少这不是他们的主要业务。

          于是他们联系了其他公司并签订了合同。如果您在此处接收电源并在这两根电线上接收输出信号,它将在这些扬声器上正常播放。

          这使得音乐播放器成为界面的完美候选者。只要连接工作正常,您不在乎谁为其提供支持。

          您可以用索尼或其他方式替换 LG 的 MusicPlayer。它不会改变本田雅阁的任何事情。

          为什么不能创建抽象类的对象?

          因为你不能走进陈列室说给我一辆车。你必须提供一个专有名词。什么车?可能是本田雅阁。那时销售代理可以为您提供一些东西。

          为什么不能创建接口的对象? 因为你不能走进陈列室说给我一份音乐播放器的合同。它没有帮助。接口位于消费者和提供者之间,只是为了促进达成协议。您将如何处理该协议的副本?它不会播放音乐。

          为什么接口允许多重继承?

          接口不被继承。实现了接口。 接口是与外部世界交互的候选者。 本田雅阁有一个加油接口。它有给轮胎充气的接口。还有用来给足球充气的软管。所以新代码如下所示:

          abstract class Car
          {
              string color;
              int speed;
          }
          class HondaAccord : Car, IInflateAir, IRefueling
          {
              MusicPlayer musicPlayer;
          }
          

          而英文会这样写:“Honda Accord is a Car 支持充气轮胎和加油”。

          【讨论】:

          • 虽然这个答案有其自身的优点,但它的大部分结论都取决于语言。例如,C++/hack 允许多重继承,并且接口和抽象类之间的区别只是按照惯例:可以通过放置抽象类来替换所有接口
          【解决方案6】:

          抽象类与接口的话题主要是关于语义的。

          抽象类在不同的编程语言中通常作为接口的超集,除了一件事,即您可以实现多个接口,但只能继承一个类。

          接口定义某事必须能够做什么;类似于合约,但不提供它的实现。

          抽象类定义什么是,它通常托管子类之间的共享代码。

          例如Formatter 应该能够format() 某事。描述类似情况的通用语义是创建一个接口IFormatter,声明format(),其行为类似于合同。但是IFormatter 并没有描述某物是什么,而只是描述了它应该能够做什么。描述事物实际是什么的通用语义是创建一个类。在这种情况下,我们创建了一个抽象类......所以我们创建了一个抽象类Formatter,它实现了接口。这是一个非常具有描述性的代码,因为我们现在知道我们有一个 Formatter,而且我们现在知道每个 Formatter 必须能够做什么。

          还有一个非常重要的主题是文档(至少对某些人来说......)。在您的文档中,您可能想在您的子类中解释 Formatter 实际上是什么。拥有一个抽象类 Formatter 非常方便,您可以在子类中链接到该类的文档。这是非常方便和通用的。另一方面,如果您没有抽象类Formatter 而只有接口IFormatter,则必须在每个子类中解释Formatter 实际上是什么,因为接口是合同,您不会在接口的文档中描述 Formatter 实际上是什么——至少这不会是常见的事情,而且你会破坏大多数开发人员认为正确的语义。

          注意:让抽象类实现接口是一种非常常见的模式。

          【讨论】:

            【解决方案7】:

            之所以称为接口,是因为它为调用者(或例如 COM 客户端)提供了由某个类实现的方法的接口。通过多态地将对象指针转换为对象的类实现的接口类型,它限制了对象对其实现的函数和接口成员的访问,与 coclass 可能实现的其他 COM 接口分开。客户端不需要知道什么类实现了接口或者类中还有哪些其他方法;对象呈现为它知道的接口的实例(类的实例已被多态地转换为接口实例,它是类的子实例),它只是通过调用接口上的方法来使用接口接口实例。实际实现的所有细节和不同接口实现的无关功能/细节都与调用者期望的接口分开——调用者只使用它与对象的接口(接口实例及其作为对象一部分的虚拟表指针) ),并调用底层对象实现,而调用者不必知道实现的位置或细节。通过接口访问对象(接口类型的指针)是一种封装形式,它在语法上防止对对象的未经授权的访问,以及隐藏与接口及其定义的个性无关的实现细节和其他功能。

            接口是所有方法都是虚拟和抽象的(抽象在 C++ 中称为纯虚拟;所有抽象方法都包含虚拟说明符,因此是虚拟的)。抽象类是其中至少一个方法是虚拟的并指定为抽象(或 C++ 中的纯虚拟)。其他细节因语言而异。所有接口属性在 java 中都是隐式的public static final,但它们不在 C++ 中。 Java 允许在抽象类中使用非静态属性,但 C++ 允许在两者中使用它们。任何一种语言中的属性都不能是虚拟的/抽象的。

            【讨论】:

              【解决方案8】:

              相似之处
              两者都强制扩展或实现它们的类覆盖基方法。

              区别

              1. 一个类可以实现多个接口。
              2. 一个类只能从一个抽象类扩展。
              3. 接口中声明的字段必须是staticfinal,因为从此类实现创建的所有对象共享相同的值。
              4. 在抽象类中,字段可以命名但不分配。子类可以覆盖它们。

              用例

              1. 抽象类用于密切相关或具有几乎相同功能和行为的子类。
              2. 接口用于不相关的类,您希望强制执行某种事情或行为,因为它只是没有实现的合同。

              【讨论】:

                猜你喜欢
                • 2010-11-13
                • 2013-02-17
                • 2018-10-11
                • 2010-12-12
                • 1970-01-01
                • 2012-04-28
                • 2019-10-17
                相关资源
                最近更新 更多