LSP定义指出,如果S是T的子类型,则程序中类型T的对象可以用类型S的对象替换,而不改变该程序的任何期望属性。
例如,我有以下类是否违反(前提条件无法在子类型中加强)。我试图围绕这个问题,有人可以提供一个很好的例子来理解它。
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
LSP原则通过接口工作,即对象/值中的公共接口。对于Python,您拥有公共的属性和方法,因此,如果您要实现接口,则必须遵守它。在您的示例中,Switch
类仅定义关于其属性的接口,即,它具有ip
和dc
字段。既然你在super
和CiscoSwitch
中调用JuniperSwitch
,它们都有这些字段,因此实现了Switch
的“接口”,它们可能会替换它。
现在,让我们来解决你提到的条件:
假设您有一个接口,其方法可以为形状着色,并且此方法仅接受十六进制颜色("#123456"
)或rgb颜色((123,124,125)
)。假设您创建了一个实现此接口的Rectangle类,但它只接受rgb颜色。你正在加强前提条件。如果你的代码中有这一行:generic_shape.color("#123456")
你不能在其中替换你的Rectangle,所以你破坏了LSP。
一个经典的例子是返回None
的方法不应该返回None
。假设在Shape界面中,您有一个getSide
方法,并且您创建了一个Circle
类,并且在实现此方法时,您将返回None
。这打破了调用者的期望并可能导致意外错误:
side = generic_shape.get_side() # suppose it is a circle
scaled_side = side * 2 # you get an error
在我看来,这个更复杂,因为它很难明确。我能想到的唯一例子是保持属性非空,假设在你的例子中你有一个不使用IP的Switch(可能使用MAC-addr),如果Switch接口期望ip
字段不应该是None,您的MAC-Switch将代理此接口。
我希望它有所帮助!