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

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

接口:

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

抽象类:

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

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

另请参阅:

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


当前回答

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

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

例如:

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

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

其他回答

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

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

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

接口是执行特定行为的轻量级方式。这是一种想法。

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

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

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

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

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

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

简单来说,我想使用

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

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

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

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

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

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

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

Jeffrey Richter通过C#从CLR复制。。。

我经常听到这样一个问题,“我应该设计一个基类型还是一个接口?”答案并不总是清晰明了。

以下是一些可能对您有所帮助的指南:

■■ IS-A与CAN-DO关系A类型只能继承一个实现。如果导出类型不能声明与基类型的IS-A关系,不要使用基类型;使用接口。接口意味着CAN-DO关系。如果CAN-DO功能似乎属于对于各种对象类型,使用接口。例如,类型可以转换自身的实例类型可以将其自身的实例序列化(ISerializable),注意,值类型必须从System.ValueType派生,因此不能可以从任意基类派生。在这种情况下,您必须使用CAN-DO关系并定义接口。

■■ 易用性作为开发人员,定义从基类型,而不是实现接口的所有方法。基本类型可以提供许多功能,因此派生类型可能只需要对其行为进行相对较小的修改。如果提供接口,则新类型必须实现所有成员。

■■ 一致的实施无论接口合同记录得多么好每个人都不可能100%正确地履行合同。事实上,COM这就是为什么某些COM对象只能与微软Word或Windows Internet Explorer。通过为基础类型提供默认实现,您首先使用一种有效且经过良好测试的类型;那么你可以修改需要修改的零件。

■■ 版本控制如果向基类型添加方法,则派生类型继承新方法,您开始使用一种有效的类型,用户的源代码甚至不必重新编译。向接口添加新成员将强制接口的继承者更改它的源代码并重新编译。