可能是重复问题:
从矩形派生正方形是否违反了里氏替换原则?
应用LSP,有人能给出一个正方形和矩形的实现吗?
我读过这本书 - 《Head First面向对象分析与设计》,他们说如果正方形继承自矩形,则违反了LSP但没有适当的实现。
有人想试试吗?
可能是重复问题:
从矩形派生正方形是否违反了里氏替换原则?
应用LSP,有人能给出一个正方形和矩形的实现吗?
我读过这本书 - 《Head First面向对象分析与设计》,他们说如果正方形继承自矩形,则违反了LSP但没有适当的实现。
有人想试试吗?
如果将正方形和矩形定义为不可变对象,那么就不会违反LSP原则。
问题在于,如果可以独立改变矩形的宽度和高度,而正方形是一种特殊的矩形,那么你就可以改变一个正方形使其不再是正方形。
你最好在构造函数中传递一个约束条件(例如bool square
),将其存储为字段,并在计算“正方形”时检查字段(x、y、w、h?),从而加快这些计算的速度。
你可以使得如果设置了“square”约束,则设置宽度或高度会自动导致另一个匹配。 set(x, y, w, h)
方法始终有效,但如果参数不是正方形,则会抛出IllegalArgumentException
或类似异常。
克林顿说得最好:这取决于“is”的定义是什么
对于一个正方形来说是矩形的不可动摇的直觉来自我们的数学训练。数学对象是不可变和无标识的。如果你的程序确实是以数学意义上的正方形和矩形对象进行建模,那么正方形应该是矩形的子类型,并且它们应该是不可变的。任何适用于矩形的数学操作也适用于正方形。
然而,你的程序可能不是在建模数学对象。也许你正在建模图形屏幕对象。其中有数学方面,但还有更多。那么我们就陷入了困境。也许将矩形设计为正方形的子类型会更好,考虑到您想要对它们进行的所有操作。那么这完全违反了我们的数学直觉,我们不希望在设计中出现这种混淆。
这是一个可怕的事实:OOP是平庸的。你可能认为一些非常聪明的人进行了一些宏伟的研究,并提出了这个万能的编程模型。对于每一个难题,都有一个完美的解决方案,你不知道它是因为你还没有在理解这个神圣的启示方面变得足够出色。人们在OOP方面的争论比宗教敌人更有热情,他们相互扔大词汇和抽象概念,引用古老的文本中的原则和惯例,而这些文本实际上没有人能够真正理解。
public class Rectangle {
int width;
int height;
public Rectangle(int w, int h) {
width = w;
height = h;
}
//getWidth(), getHeight, getArea(), etc, but no setters.
}
public Square extends Rectangle {
public Square(int side) {
super(side, side);
}
}
scale()
方法,您可以以符合LSP的方式扩大矩形和正方形,但是在矩形上覆盖的接受两个边的grow()
方法,当然会违反LSP,因为正方形需要正确地重写它。
四边形(Quadrilateral)
继承,而四边形
又继承自形状(Shape)
。所有的四边形都有四条边、四个角等。 - David R Tribble