类层次结构设计 - 接口 + 基类 vs. 抽象类

4
有时我在想我们为什么需要接口和抽象类这两个不同的东西:
1. 如果你只是想要多种实现以进行设计并且需要在开发期间编写代码,那么接口是我们最好的选择。 2. 如果你想要重用代码,那么我们可能会使用抽象类。
然而,我看到了一些既非接口又非抽象类的情况。
在某些设计中,它像这样:接口 > 基类 > 子类。
因此,基类实现了所有方法,然后子类从中继承定义。为什么我们不能使用抽象类代替这种设置?或者说这是一个有缺陷的设置吗?
8个回答

11

最简单的推理是,如果一个对象具有IS-A关系,则使用(抽象)基类。例如,马是一种动物。

如果存在CAN关系,则考虑使用接口,例如如果一只鸭子可以飞,可以为其使用IFlying作为能够飞行的鸭子的接口。


2
这是一个非常简洁易记的好答案。 - Matt Wilko
哇!我第一次看到这个“Is”和“can”的例子。特别是在模拟分类法(或对现实世界的编码抽象)中,这很有意义。你能提供一个好的链接供进一步阅读吗?谢谢! - Vance McCorkle
1
@VanceMcCorkle https://www.w3resource.com/java-tutorial/inheritance-composition-relationship.php,https://www.baeldung.com/java-inheritance-composition - Michel Keijzers

3

接口可以用于将多个接口实现到一个类中。在C#中,你不能从多个类派生。


3

这个网站上关于抽象类和接口的回答将帮助您理解它们之间的设计差异。


3

这是一种设计和个人品味的问题,通常当你声明一个接口时,你并不真正关心具体的实现方式,而只关心接口应该提供的封装功能。

拥有抽象类确实定义了一些指定的行为,但这并不总是你想要的。

同时,拥有抽象类会禁止你继承多个类,因此会限制它可以拥有的功能。

在设计类层次结构时,你会问自己“在这种情况下应该使用什么对象?”并为该功能定义一个接口,然后,在提供实现时,你可以意识到某些功能应该被分组并重复使用于某些子类中,但这是随后才会发生的。


2
由于C#中禁止使用多重继承,但允许实现多个接口。

2

接口实际上是功能的一种契约,指定了某些方法和属性。可针对该接口编写代码段,而不需要任何实现细节的知识。

抽象类可能实现一些接口,但也可能包含所有派生类型都可能需要的一些公共功能。它还可以包括抽象或虚拟方法/属性,允许派生类型自定义部分功能。

考虑这样一种情况:您构建了一些对象模型,并使用接口定义该模型的结构,但您希望允许代码的使用者在不影响核心设计的情况下编写自己的实现。然后您可以为一个实现构建自己的基类。派生类型将继承此基类,而此基类又实现了对象模型的接口。接着其他人可能会编写自己的实现,但想要与您现有的实现具有不同的功能或行为。因此,他们编写自己的基类以及扩展其自己的派生类型。

按照这种方案,没有真正的理由不能同时使用抽象类和接口。这完全取决于您的目的以及如何构建您的代码。


2

接口定义了一组属性和功能,类必须实现并可以由任意数量的类实现。基类也可以实现接口。例如,许多不同的基类可能使用IComparable接口。


0

接口的主要规则如下:

  1. 所有方法都应该是抽象的
  2. 没有实现
  3. 接口可以扩展任意数量的接口
  4. 所有字段都应该是公共的、静态的和不可变的
  5. 所有方法都应该在继承类中被重写

由于这是一个C#线程,当您声明某个内容为接口时,IDE会强制执行所有相关规定。 - Void

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接