里氏替换原则示例

Liskov Substitution Principle example

LSP对我来说是SOLID中最难理解的。

LSP 声明程序中的对象应该可以用其子类型的实例替换,而不会改变程序的正确性。

因此,如果我们有这个典型的矩形 - 正方形示例:

rect = new Rectangle();

rect.width  = 10;
rect.height = 20;

然后我们尝试测试一下:

assert 10 == rect.width
assert 20 == rect.height

一切正常,但是当我们试图说正方形也是长方形时,我们使用:

rect = new Square();

正方形其实高宽都一样,会导致测试失败

那么我们如何解决这个问题呢?在这种情况下,我们将 类 分隔为方形和矩形以避免 LSP 问题?

在这个特定的例子中,解决方案是 而不是 SquareRectangle 派生,因为虽然我们通常说继承是 'is a' 关系,您应该将其视为 'behaves like' 关系。因此,尽管从数学上讲,SquareRectangle,但 Square 肯定不会 表现得 Rectangle(正如您在上面的代码)。

相反,让它们都来自同一个基数 class:

public abstract class Shape { }

public class Square : Shape { 
    public int Size;
}

public class Rectangle : Scape { 
    public int Height;
    public int Weight;
}