哈工大软件构造复习——LSP原则,协变和逆变
(防扒链接)
写在前面
在复习软件构造课程的过程中,LSP原则,协变和逆变是课程后期的重点之一,鉴于其难度较高,特总结此篇博客以更好地学习这些知识。
一、LSP原则
LSP原则,即Liskov Substitution Principle,常译为里氏替换原则:
只要父类能出现的地方,子类就可以出现,并且替换为子类也不会产生任何错误或异常。
常用如下:
- 子类型可以增加方法,但不可删
- 子类型需要实现抽象类型中的所有未实现方法
- 子类型中重写的方法必须有相同或子类型的返回值或者符合协变的参数
- 子类型中重写的方法必须使用同样类型的参数或者符合逆变的参数。
- 子类型中重写的方法不能抛出额外的异常,子类型也可以不抛出异常。异常必须满足协变。
- Same or stronger invariants 更强的不变量
- Same or weaker preconditions 更弱的前置条件
- Same or stronger postconditions 更强的后置条件
在实际操作中需要注意以下三种情况:
(1)所有使用基类的地方必须能透明地使用子类替换,而程序的行为没有任何变化(不会产生运行结果错误或异常)。只有这样,父类才能被真正复用,而且子类也能够在父类的基础上增加新的行为。也只有这样才能正确的实现多态。
(2)当一个类继承了另一个类时,子类就拥有了父类中可以继承下来的属性和操作。但如果子类覆盖了父类的某些方法,那么原来使用父类的地方就可能会出现错误,因为表面上看,它调用了父类的方法,但实际运行时却调用了被子类覆盖的方法,而这两个方法的实现可能不一样,这就不符合LSP原则。
(3)LSP原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。
LSP原则简而言之就是规范继承时子类的一些书写规则:
前置条件不能强化 后置条件不能弱化 不变量要保持或增强
子类型方法参数:逆变子类型方法的返回值:协变
异常类型:协变
这里出现了两个易混淆的名词:协变和逆变,在下文将给出介绍。
二、协变和逆变
逆变与协变用来描述类型转换(type transformation)后的继承关系
定义:如果A、B表示类型,f(⋅)表示类型转换,≤表示继承关系
(比如,A≤B表示A是由B派生出来的子类)
f(⋅)是逆变(contravariant)的,当A ≤ B时有f(B) ≤ f(A)成立;
f(⋅)是协变(covariant)的, 当A ≤ B时有f(A) ≤ f(B)成立;
f(⋅)是不变(invariant)的, 当A ≤ B时上述两个式子均不成立,即f(A)与f(B)相互之间没有继承关系。
1、协变
如果A是B的子类,那么A中的类型T也是B中类型T’的子类,这就是协变。
父类型->子类型:越来越具体(specific)。
在LSP中,返回值和异常的类型:不变或变得更具体 。
2、逆变
如果A是B的子类,但是A中的类型T是B中类型T’的祖先类型,那么就是逆变。
父类型->子类型:越来越抽象(abstract)。
参数类型:要相反的变化,不变或越来越抽象。
相关文章
- 金融服务领域的大数据:即时分析
- 影响大数据、机器学习和人工智能未来发展的8个因素
- 从0开始构建一个属于你自己的PHP框架
- 如何将Hadoop集成到工作流程中?这6个优秀实践必看
- SEO公司使用大数据优化其模型的5种方法
- 关于Web Workers你需要了解的七件事
- 深入理解HTTPS原理、过程与实践
- 增强分析:数据和分析的未来
- PHP协程实现过程详解
- AI专家:大数据知识图谱——实战经验总结
- 关于PHP的错误机制总结
- 利用数据分析量化协同过滤算法的两大常见难题
- 怎么做大数据工作流调度系统?大厂架构师一语点破!
- 2019大数据处理必备的十大工具,从Linux到架构师必修
- OpenCV中的KMeans算法介绍与应用
- 教大家如果搭建一套phpstorm+wamp+xdebug调试PHP的环境
- CentOS下三种PHP拓展安装方法
- Go语言HTTP Server源码分析
- Go语言HTTP Server源码分析
- 2017年4月编程语言排行榜:Hack首次进入前五十