1700453640
此处是一个手枪,用来射击,如果使用了子类型ToyGun,士兵将会拿着玩具枪来杀人,可是射不出子弹呀!如果在CS游戏中有这种事情发生,那就等着被人爆头,然后看着自己凄凉的倒地。
1700453641
1700453642
此处不能替换的原因是子类型没有完全实现父类型的方法,而是丢弃了父类型的行为能力,导致子类型不具备父类型的部分功能了。
1700453643
1700453644
(2)前置条件可以被放大
1700453645
1700453646
方法中的输入参数称为前置条件,它表达的含义是你要让我执行,就必须满足我的条件。前置条件是允许放大的,这样可以保证父类型行为逻辑的继承性,比如有这样的代码:
1700453647
1700453648
class Base{
1700453649
1700453650
public void doStuff(HashMap map){
1700453651
1700453652
}
1700453653
1700453654
}
1700453655
1700453656
class Sub extends Base{
1700453657
1700453658
public void doStuff(Map map){
1700453659
1700453660
}
1700453661
1700453662
}
1700453663
1700453664
这是Java的重载实现,子类型在实现父类型的同时也具备了自己的个性,可以处理比父类型更宽泛的任务,而且不会影响父类的任何行为,例如在如下代码中把父类型替换为子类型就不会有任何变化:
1700453665
1700453666
public static void main(String[]args){
1700453667
1700453668
Base b=new Base();
1700453669
1700453670
b.doStuff(new HashMap());
1700453671
1700453672
}
1700453673
1700453674
此时,把Base全部替换为Sub,所有的行为全部还是由父类型Base实现的,子类型的doStuff方法并没有调用,也就是说,子类型可以在扩展前置条件的情况下保持类的可替换性。
1700453675
1700453676
(3)后置条件可以被缩小
1700453677
1700453678
父类型方法的返回值是类型T,子类同名方法(重载或覆写)的返回值为S,那么S可以是T的子集,这里又分为两种情况:
1700453679
1700453680
若是覆写,父类型和子类型的方法名名称就会相同,输入参数也相同(前置条件相同),只是返回值S是T类型的子集,子类型替换父类型完全没有问题。
1700453681
1700453682
若是重载,方法的输入参数类型或数量则不相同(前置条件不同),在使用子类型替换父类型的情况下,子类型的方法不会被调用到的,已经无关返回值类型了,此时子类依然具备可替换性。
1700453683
1700453684
增强类的可替换性,则增强了程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,非常完美!
1700453685
1700453686
1700453687
1700453688
[
上一页 ]
[ :1.70045364e+09 ]
[
下一页 ]