里氏替换原则(LSP)对子类型提出了四项行为要求(直接来自维基百科):
有一个有点著名的方形-矩形(或圆形-椭圆形)问题会破坏 LSP,但我想了解它实际上破坏了哪些条件。
问题如下:我们有一个
Square
,其中 is-a Rectangle
。我们可以设置 w
的宽度 h
和高度 Rectangle
,在 Square
的情况下,它们会被覆盖以同时修改宽度和高度(即 Square.setWidth
是实现将 w
和 h
设置为相同的值)。
现在,我们引入另一个类方法
squeeze
,它将h
更改为h/2
。如果在 Square
上调用此方法,则会违反 w==h
的不变量。
直观地说,我们会从上面打破不变条件,但问题似乎是我们在子类型中加强了一个不变量(原来的不变量只是
w,h >= 0
)。
我们也没有削弱后置条件。再说一次,如果有什么事情的话,我们必须加强后置条件,即在对
w==h
进行任何操作之后,Square
不存在Rectangle
。
我不明白先决条件有何相关性。
对于历史约束,我们只使用了类方法。
如果将正方形视为矩形,则里氏替换原理就会出现问题,因为两者的行为不同。
如果将 5x5 矩形 的高度更改为 6,它将变成 5x6 矩形。如果你对一个正方形做同样的事情,它就会变成一个 6x6 的正方形。
因此,如果您有一个测试用例在更改高度后检查宽度(或面积),则两个形状之间的行为会有所不同。