1700454934
1700454935
}
1700454936
1700454937
}
1700454938
1700454939
代码运行结果如下所示:
1700454940
1700454941
父类被执行……
1700454942
1700454943
那我们再把里氏替换原则引入进来会有什么问题?有父类的地方子类就可以使用,好,我们把这个Client类修改一下,源代码如代码清单2-18所示。
1700454944
1700454945
代码清单2-18 采用里氏替换原则后的业务场景类
1700454946
1700454947
public class Client{
1700454948
1700454949
public static void invoker(){
1700454950
1700454951
//有父类的地方就有子类
1700454952
1700454953
Son f=new Son();
1700454954
1700454955
HashMap map=new HashMap();
1700454956
1700454957
f.doSomething(map);
1700454958
1700454959
}
1700454960
1700454961
public static void main(String[]args){
1700454962
1700454963
invoker();
1700454964
1700454965
}
1700454966
1700454967
}
1700454968
1700454969
代码运行后的结果如下所示:
1700454970
1700454971
子类被执行……
1700454972
1700454973
完蛋了吧?!子类在没有覆写父类的方法的前提下,子类方法被执行了,这会引起业务逻辑混乱,因为在实际应用中父类一般都是抽象类,子类是实现类,你传递一个这样的实现类就会“歪曲”了父类的意图,引起一堆意想不到的业务逻辑混乱,所以子类中方法的前置条件必须与超类中被覆写的方法的前置条件相同或者更宽松。
1700454974
1700454975
4.覆写或实现父类的方法时输出结果可以被缩小
1700454976
1700454977
这是什么意思呢,父类的一个方法的返回值是一个类型T,子类的相同方法(重载或覆写)的返回值为S,那么里氏替换原则就要求S必须小于等于T,也就是说,要么S和T是同一个类型,要么S是T的子类,为什么呢?分两种情况,如果是覆写,父类和子类的同名方法的输入参数是相同的,两个方法的范围值S小于等于T,这是覆写的要求,这才是重中之重,子类覆写父类的方法,天经地义。如果是重载,则要求方法的输入参数类型或数量不相同,在里氏替换原则要求下,就是子类的输入参数宽于或等于父类的输入参数,也就是说你写的这个方法是不会被调用的,参考上面讲的前置条件。
1700454978
1700454979
采用里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,非常完美!
1700454980
1700454981
1700454982
1700454983
[
上一页 ]
[ :1.700454934e+09 ]
[
下一页 ]