抽象超类的抽象子类是否违反 LSP?

Do abstract subclasses of an abstract superclass violate LSP?

我正在使用 SOLID 原则,特别是里氏替换原则 (LSP)。

我有一个名为 Button 的抽象 class,它定义了不同的方法,不同的子classes 扩展它来定义其中的一些方法。例如,我有一个名为 PauseButton 的子 class,它仅实现抽象 class.

中的 3 个方法

是否认为违反了 LSP?

Liskov's Substitution Principle 的核心思想是,只要您可以使用该类型的实例,就可以使用该子类型的实例。子类型可能更专业,但它应该遵守相同的合同。

在您的示例中,如果 PauseButton 的所有“方法”(我们在 UML 中称为“操作”)都符合为 Button 定义的合同,那么 PauseButtonButton 实现了 LSP .这不仅仅是实现方法,还要确保方法兼容:

  1. PauseButton可能不会强化Button的前置条件。 IE。如果满足执行Button方法的条件,您应该也能够执行相应的PauseButton方法。
  2. PauseButton 可能不会削弱 Button 的后置条件。 IE。如果 Button 对方法作出一些承诺,PauseButton 必须至少履行相同的承诺。
  3. Button 的不变量(应该始终为真的逻辑条件)也应该是 PauseButton 的不变量。 PauseButton 可能有额外的不变量。
  4. History constraint: 粗略地说,这意味着 PauseButton 是一个 ButtonPauseButton 方法不应该直接修改它的 Button 状态,而不使用方法Button。没有捷径。

在抽象子类的情况下,验证 LSP 更加微妙,因为我们无法查看直接实例。然而,子类可以由提供缺失方法的具体子类间接实例化:

  • 如果您实现的三种 PauseButton 方法中至少有一种违反了 LSP(即与 Button 中的相同方法不兼容),则 PauseButton 违反了 LSP。
  • 但是如果所有这三个方法都兼容,并且如果 PauseButton 没有重新定义其他方法的契约,你可以假设 PauseButton 是 LSP-Compliant :你可以创建PauseButton 的具体子类将是兼容的,即使在现阶段这样的子类不存在。这满足了互换性的要求。