一.概念
首先,里氏替换原则LSP的全拼是.LSP(The Liskov Substitution Principle) ,她提出的这项原则关键在于:一个软件实体如果使用的是一个基类的话,一定适用于其 子类,而且根本不能觉察出基类对象和子类对象的区别。
抽象概念:
“若对于类型S的任一对象o1,均有类型 T的对象o2存在,使得在T定义的所有程序P中,用o1 替换o2之后,程序的行为不变,则S是T的子类型”。
具体定义:
在一个软件系统中,子类应该能够完全 替换任何父类能够出现的地方,并且经过替换后, 不会让调用父类的客户程序从行为上有任何改变。
二.Liskov替换原则的意义
-
在客户程序在调用某一个类时,实际上是对该类的整个继 承体系设定了一套约束,继承体系中的所有类必须遵循这 一约束,即前置条件和后置条件必须保持一致。这为对象 继承加上了一把严格的枷锁。
-
LSP原则对于约束继承的泛滥具有重要意义。
-
所有派生类的行为功能必须和使用者对其基类的期望保 持一致,如果派生类达不到这一点,那么必然违反里氏替 换原则。
-
里氏代换原则就是在设计时避免出现派生类与基类不一致 的行为。
-
里氏代换原则目的就是要保证继承关系的正确性。
三.里氏代换原则实例
1.典型的正方形不是长方形问题。
长方形类
public class Rectangle{
setWidth(int width){
this.width=width;
}
setHeight(int height){
this.height=height
}
}
正方形类
public class Square extends Rectangle
{
setWidth(int width){
this.width=width;
this. height=width;
}
setHeight(int height){
this.setWidth(height);
}
}
测试类
public void resize(Rectangle r){
while(r.getHeight()<=r.getWidth){
r.setHeight(r.getWidth+1);
}
}
在这个测试类中,我们给传入一个Rectangle的对象,设置它的长宽为5和10,那么在测试类运行结束时,长宽为11和10,如果传入了Square 的对象,则会一直无限运行下去,即达到了两种完全不同的效果,则这里的子类对象不能替代掉父类,所以违背了里氏代换原则。
四.里氏代换原则引申出新的规则
只要有可能,不要从具体类继承,而应该从抽象类继 承或是实现接口。
行为集中的方向是向上的(抽象类)。
数据集中的方向是向下的(具体类)。