Liskov替换原则 - 如何建模方形和矩形

时间:2010-12-03 18:20:14

标签: java oop design-patterns

  

可能重复:
  Is deriving square from rectangle a violation of Liskov's Substitution Principle?

通过应用LSP,任何人都可以给我一个Square和Rectangle的实现吗?

我读过这本书 - “首先面向对象的分析和设计”,他们说如果Sqaure继承自Rectangle,它违反了LSP但没有正确的实现。

有人想试试吗?

5 个答案:

答案 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比宗教敌人更热心,互相投掷大词和抽象概念,引用古代文本中没有人真正理解的原则和惯例。