需要明白理解liskov替代原则

问题描述 投票:0回答:1

LSP定义指出,如果S是T的子类型,则程序中类型T的对象可以用类型S的对象替换,而不改变该程序的任何期望属性。

  1. 子类型不能强化前提条件
  2. 后置条件不能在子类型中被削弱。
  3. 超类型的不变量必须保留在子类型中。

例如,我有以下类是否违反(前提条件无法在子类型中加强)。我试图围绕这个问题,有人可以提供一个很好的例子来理解它。

Class Switch:
   def __init__(self,ip,dc):
       self.ip=ip
       self.dc=dc

class CiscoSwitch(Switch):
   def __init__(self,ip,dc,zone):
       super().__init__(ip,dc)
       self.zone=zone

class JuniperSwitch(Switch):
   def __init__(self,ip,dc,zone):
       super().__init__(ip,dc)
       self.zone=zone
python oop solid-principles liskov-substitution-principle
1个回答
0
投票

LSP原则通过接口工作,即对象/值中的公共接口。对于Python,您拥有公共的属性和方法,因此,如果您要实现接口,则必须遵守它。在您的示例中,Switch类仅定义关于其属性的接口,即,它具有ipdc字段。既然你在superCiscoSwitch中调用JuniperSwitch,它们都有这些字段,因此实现了Switch的“接口”,它们可能会替换它。

现在,让我们来解决你提到的条件:

  1. 子类型不能强化前提条件

假设您有一个接口,其方法可以为形状着色,并且此方法仅接受十六进制颜色("#123456")或rgb颜色((123,124,125))。假设您创建了一个实现此接口的Rectangle类,但它只接受rgb颜色。你正在加强前提条件。如果你的代码中有这一行:generic_shape.color("#123456")

你不能在其中替换你的Rectangle,所以你破坏了LSP。

  1. 子类型中的后置条件不能被削弱

一个经典的例子是返回None的方法不应该返回None。假设在Shape界面中,您有一个getSide方法,并且您创建了一个Circle类,并且在实现此方法时,您将返回None。这打破了调用者的期望并可能导致意外错误:

side = generic_shape.get_side() # suppose it is a circle
scaled_side = side * 2 # you get an error
  1. 超类型的不变量必须保留在子类型中

在我看来,这个更复杂,因为它很难明确。我能想到的唯一例子是保持属性非空,假设在你的例子中你有一个不使用IP的Switch(可能使用MAC-addr),如果Switch接口期望ip字段不应该是None,您的MAC-Switch将代理此接口。

我希望它有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.