里氏置换原则里氏置换原则的两种定义:定义一:
如果对于每一个类型是s的对象o1,都有类型为T的对象o2,使得用T定义的所有程序P在所有对象o1都代换成o2时,
程序p并没有什么变化,那么S就是T的子类型。
定义二:
所有引用基类的地方必须能够透明的使用其子类的对象。
通俗的说:只要是父类能够出现的地方子类就可以出现而且把父类替换为子类也不会产生任何的错误或者异常。反过来不可以子类出现的地方,出现父类。
为了达到这个目的,实现这个原则,我们需要遵守四条规则:即 纠纷不断,规则压制
1.子类必须完全实现父类的所有方法。
子类不可以只实现部分方法,或者空实现。
如果不能完整的实现父类的方法,或者父类的方法在子类中发生了畸变,那么建议放弃继承关系,改为依赖,聚合,组成等关系代替继承。
2.子类可以有自己的个性
子类可以有自己独特的行为,这也证明了子类出现的地方父类不一定能够胜任。
3.覆盖或者实现父类方法的时输入参数可以被扩大
要求:子类中方法的前置条件必须和超类中被覆写的方法的前置条件相同或者更宽松。
如果子类的方法输入参数的范围大于父类中被覆写方法的范围,那么当父类存在的地方被替换为子类后,程序不会变化。代码如下:
父类:father(){
void pirnt(hashMap){
print(father);
};
}
子类:son extends father(){
void print (Map map){
print(son);
};
}
map的范围大于hashMap,那么当父类被替换成子类,即用父类对象去调用父类方法和用子类对象调用都会调用父类中的方法。
main(){
father f=new father();
son f=new son(); 子类置换了父类并么有什么不同,指定的结果都是打印father
hashMap hash=new hashMap();
f.print(hash);
}
如果相反,子类的范围小于父类,当父类对象被置换为子类,那么很可能就会进入子类的方法中,
父类:father(){
void pirnt(Map){
print(father);
};
}
子类:son extends father(){
void print (hashMap map){
print(son);
};
}
main(){
father f=new father(); 打印father
son f=new son(); 置换后打印son
hashMap hash=new hashMap();
f.print(hash);
}
4.覆写或者实现父类中的方法时输出结果可以被缩小
|
|