里氏代换原则

170 阅读2分钟

里氏代换原则

任何基类可以出现的地方,子类一定可以出现

通俗来讲,子类继承父类的时候,除了添加新的方法完成新增功能外,尽量不要去重写父类的方法

如果你重写了父类的方法,整个继承体系的可复用性就会变差,尤其是运用多态比较频繁的时候,程序运行出错的概率会非常大!

🌰举个栗子

❌错误示范

在数学中,正方形是一个长和宽相等的长方形,所以我们开发一个与几何图形相关的软件系统,就可以直接让正方形继承自长方形

长方形类:

//Rectangle.class
private int length;
private int width;
​
public void setLength(int length) {
    this.length = length;
}
​
public void setWidth(int width) {
    this.width = width;
}
​
//省略getter

正方形类继承自长方形类,但是这里为了使长宽相同,重写了父类的setter:

//Square.class
private int length;
private int width;
​
public void setLength(int length) {
    //保证了长宽相同
    this.length = length;
    this.width = width
}
​
public void setWidth(int width) {
    //保证了长宽相同
    this.width = width;
    this.length = length;
}

现在我们有一个需求:为长方形实例拓宽,直到宽比长更大:

//Test.class
Square sq = new Square();
sq.setLength(20);
​
public void resize(Rectangle rect) {
    while(rect.getLength() >= rect.getWidth()) {
        rect.setWidth(rect.getWidth()++);
    }
}

方法中进行判断,当实例的宽比长小,就给宽++,最终实现宽大于长的目的。

如果传入的是长方形,则可以正常执行,但如果传入了正方形,正方形的宽和高都在不停变化,始终保持一致,这样就会导致无限循环而报错。

以上就是错误的示范,错误原因就在于正方形类重写了父类长方形中的getter,导致出现错误。

✔正确示范

由错误案例我们就能得出一个结论:正方形不能简单地抽象为长方形,需要将他们分而治之。

我们重新设计他们之间的关系。抽象出来一个四边形接口(Quadrilateral),让Rectangle类和Square类实现Quadrilateral接口:

quadrilateral.png

这样resize方法中只能传入长方形对象,而不能传入正方形对象,就避免了传入正方形进入死循环的问题,完美的符合了里氏代换原则!