可能重复:
Is deriving square from rectangle a violation of Liskov's Substitution Principle?
通过应用LSP,任何人都可以给我一个Square和Rectangle的实现吗?
我读过这本书 - “首先面向对象的分析和设计”,他们说如果Sqaure继承自Rectangle,它违反了LSP但没有正确的实现。
有人想试试吗?
答案 0 :(得分:12)
如果你使Square和Rectangle不可变,那么你就不会违反LSP。
问题是,如果您可以独立更改矩形的宽度和高度,而Square是一个矩形,那么您可以将Square更改为不是正方形。
答案 1 :(得分:1)
我会说:不要
正方形是矩形的特例。所以:使用矩形。目前尚不清楚是否有任何合理的理由可以选择一个明确的方阵。
当然,这实际上取决于你对这些形状做了什么。 LSP是否满足取决于您对形状的操作。
答案 2 :(得分:0)
你最好在构造函数中传递一个约束(bool square
会做)将其存储为字段,并在计算“正方形”时检查字段(x,y,w,h?) '因此加快了这些计算的要素。
你可以这样做,如果设置'square'约束,设置width或height会导致另一个自动匹配。 set(x, y, w, h)
方法始终有效,但如果参数没有给出正方形,则会抛出IllegalArgumentException
或类似方法。
答案 3 :(得分:0)
如果它们是不可变的,如上所述,它不违反LSP:
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。
答案 4 :(得分:0)
正方形是矩形的不可动摇的直觉来自我们的数学训练。数学对象是不可变的,没有身份。如果你的程序确实是在数学意义上对方形和矩形对象进行建模,那么Square应该是Rectangle的子类型,它们应该是不可变的。任何适用于Rectangle的数学运算都适用于Square。
但是,您的程序可能无法建模数学对象。也许你正在建模图形屏幕对象。它们中有数学方面,但还有更多。然后我们一团糟。也许最好将Rectangle设计为Square的子类型,考虑到你想要放在它们上的所有操作。然后它完全违背了我们的数学直觉,我们不希望在设计中出现这种混乱。
这是一个可怕的事实:OOP是meh。你可能认为一些超级聪明的人做了一些宏伟的研究,并提出了这种无所不能的编程模型。对于每个谜题都有一个完美的解决方案,你只是不知道它,因为你没有变得足够理解这个神圣的启示。人们争论OOP比宗教敌人更热心,互相投掷大词和抽象概念,引用古代文本中没有人真正理解的原则和惯例。