里氏替换原则示例
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 问题?
在这个特定的例子中,解决方案是 而不是 让 Square
从 Rectangle
派生,因为虽然我们通常说继承是 'is a' 关系,您应该将其视为 'behaves like' 关系。因此,尽管从数学上讲,Square
是 Rectangle
,但 Square
肯定不会 表现得 像 Rectangle
(正如您在上面的代码)。
相反,让它们都来自同一个基数 class:
public abstract class Shape { }
public class Square : Shape {
public int Size;
}
public class Rectangle : Scape {
public int Height;
public int Weight;
}
LSP对我来说是SOLID中最难理解的。
LSP 声明程序中的对象应该可以用其子类型的实例替换,而不会改变程序的正确性。
因此,如果我们有这个典型的矩形 - 正方形示例:
rect = new Rectangle();
rect.width = 10;
rect.height = 20;
然后我们尝试测试一下:
assert 10 == rect.width
assert 20 == rect.height
一切正常,但是当我们试图说正方形也是长方形时,我们使用:
rect = new Square();
正方形其实高宽都一样,会导致测试失败
那么我们如何解决这个问题呢?在这种情况下,我们将 类 分隔为方形和矩形以避免 LSP 问题?
在这个特定的例子中,解决方案是 而不是 让 Square
从 Rectangle
派生,因为虽然我们通常说继承是 'is a' 关系,您应该将其视为 'behaves like' 关系。因此,尽管从数学上讲,Square
是 Rectangle
,但 Square
肯定不会 表现得 像 Rectangle
(正如您在上面的代码)。
相反,让它们都来自同一个基数 class:
public abstract class Shape { }
public class Square : Shape {
public int Size;
}
public class Rectangle : Scape {
public int Height;
public int Weight;
}