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

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

接口:

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

抽象类:

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

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

另请参阅:

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


当前回答

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

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

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

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

其他回答

1) 接口可以被视为纯抽象类,这是相同的,但尽管如此,实现接口和从抽象类继承并不相同。当你从这个纯抽象类继承时,你定义了一个层次结构->继承,如果你实现了你不需要的接口,你可以实现任意多的接口,但是你只能从一个类继承。

2) 您可以在接口中定义属性,因此实现该接口的类必须具有该属性。

例如:

  public interface IVariable
  {
      string name {get; set;}
  }

实现该接口的类必须具有这样的属性。

接口:

不包含含义接口可以从多个接口继承(支持多重继承)成员自动公开可以包含财产、方法、事件和索引器

抽象类:

可能/可能不包含实施;至少有一个成员不会被执行。类可以从单个基类继承;不允许多重继承。成员具有访问修饰符可以包含字段、财产、构造函数、析构函数、方法、事件和索引器

这些是抽象类和接口之间的关键区别。

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

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

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

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

从编码角度

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

从设计角度

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

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

当然,理解OOP中接口和抽象类的行为(以及语言如何处理它们)很重要,但我认为理解每个术语的确切含义也很重要。你能想象if命令不能完全按照这个词的意思工作吗?此外,实际上,一些语言正在减少,甚至更多地减少界面和抽象之间的差异。。。如果碰巧有一天这两个术语几乎相同,那么至少你可以定义它们中的任何一个应该用于何处(以及为什么)。

如果你阅读一些字典和其他字体,你可能会发现同一个词有不同的含义,但有一些共同的定义。我认为我在这个网站上找到的这两个意思真的非常好,非常适合。

接口:

使分离的、有时不相容的元素能够有效协调的事物或环境。

摘要:

集中于自身的东西,集中于任何更广泛或更普遍的事物或若干事物的本质;本质

例子:

你买了一辆车,它需要燃料。

你的汽车模型是XYZ,属于ABC类型,所以它是一辆具体的汽车,一辆汽车的具体实例。汽车不是实物。事实上,它是一组抽象的标准(质量)来创建特定的对象。简而言之,Car是一个抽象的类,它是“集中于自身的任何更广泛或更一般的东西的本质”。

应使用符合汽车手册规格的唯一燃油来加注汽车油箱。实际上,没有什么可以限制您添加任何燃油,但发动机只能在指定的燃油下正常工作,因此最好遵循其要求。该要求表示,与其他同类ABC汽车一样,该公司接受一套标准燃油。

在面向对象的视图中,ABC类型的燃料不应该被声明为一个类,因为没有特定类型的汽车的具体燃料。尽管您的汽车可以接受抽象类别燃油或车辆燃油,但您必须记住,您现有的车辆燃油中只有一部分符合规范,即满足汽车手册要求的燃油。简而言之,他们应该实现ABCGenreFuel接口,该接口“……使独立的、有时不兼容的元素能够有效地协调”。

补遗

此外,我认为你应该记住class这个词的含义,它是(来自前面提到的同一个网站):

类别:

一群人或事物由于共同的属性、特征、品质或特点而被视为组成一个群体;友善的

这样,类(或抽象类)不应只表示公共属性(如接口),而是表示具有公共属性的某种组。接口不需要表示一种。它必须表示公共属性。通过这种方式,我认为类和抽象类可以用来表示不应该经常改变其方面的事物,比如人类是哺乳动物,因为它代表了某些种类。种类不应该经常改变自己。