理论性知识学习
里氏替换原则,Liskov Substitution principle(LSP)。测试
抽象定义是下面这样的设计
若是对每个类型为T1的对象O1,都有类型为T2的对象O2,使得以T1定义的全部程序P在全部的对象O1都替换成O2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。对象
通俗地解释一下blog
一个软件实体若是适用一个父类的话,那必定适用于其子类,全部引用父类的地方必须能透明地使用其子类的对象,子类对象可以替换父类对象,而程序逻辑不变。继承
引伸一下,若是子类替换父类,还必须保证程序逻辑不变,就必须知足如下几点。ip
增强程序的健壮性,同时变动时能够作到很是好的兼容性。ci
提升程序的维护性,扩展性,下降需求变动时引入的风险。编译器
代码实战1it
实现一个正方形继承长方形的场景,由于正方形是一种特殊的长方形。
定义一个长方形,以下图
定义一个正方形,以下图,重写了父类的方法。
最后执行测试方法,当宽大于等于高时,就改变宽和高。以下图
当用子类正方形替换父类时,程序就会进入无限循环,以下图
根据以上得出,子类能够实现父类的抽象方法,但不能覆盖父类的非抽象方法
代码实战2
首先定义一个简单的父类,以下图
而后定义一个子类,子类的入参类型Map比父类的入参HashMap宽松,以下图
最后测试以下图
由测试结果能够看出,child类彻底能够替换base类去执行。遵循了里式替换原则,
即当子类的方法重载父类的方法时,方法的前置条件(即方法的输入,入参)要比父类方法的输入参数更宽松。
代码实战3
仍是定义一个简单的父类,方法返回类型为HashMap,以下图
定义一个子类,实现父类抽象方法时,返回值类型为Map,编译器就会直接报错,以下图
根据以上能够得出结论
当子类的方法实现父类的方法时(重写,重载或实现抽象方法),方法的后置条件(方法的输出,返回值)要比父类更严格或相等。
我的总结
一开始学习里式替换原则时,也是不明白。最后也是慢慢理解透的。总结起来就是
子类能够替换父类,替换后,不能改变程序的运行逻辑。
也欢迎你们在评论区留下本身的见解!