LSP原则中的逆变和协变
在复习过程中,LSP原则是个很重要的内容。这里先给出LSP原则的定义。
LSP定义
Functions that use pointers or referrnces to base classes must be able to use objects of derived classes without knowing
it.(所有引用基类的地方必须能透明地使用其子类的对象。)
这个的主要作用就是规范继承时子类的一些书写规则。其主要目的就是保持父类方法不被覆盖。
也就是所有引用父类的地方,替换子类进去,不会有任何影响。
子类必须完全实现父类的方法
子类可以有自己的个性
覆盖或实现父类的方法时输入参数可以被放大
覆盖或实现父类的方法时输出结果可以被缩小
LSP是子类型关系的一个特殊定义,称为(强)行为子类型化。在编程语言中,LSP依赖于以下限制:
前置条件不能强化
后置条件不能弱化
不变量要保持或增强
子类型方法参数:逆变
子类型方法的返回值:协变
异常类型:协变
这里出现了两个生词:协变和逆变。本篇文章主要说一下这俩是啥。
逆变与协变综述:如果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)相互之间没有继承关系。
协变(Co-variance)
父类型->子类型:越来越具体(specific)。
在LSP中,返回值和异常的类型:不变或变得更具体 。
逆变(Contra-variance)
父类型->子类型:越来越抽象。
参数类型:要相反的变化,不变或越来越抽象。
来看一下应用:
数组是协变的:一个数组A[ ] ,可能包含了A类型的实例或者A的任何子类型的实例
1 Number[] numbers = new Number[2];
2 numbers[0] = new Integer(10);
3 numbers[1] = new Double(3.14);
4
5 Integer[] myInts = {1,2,3,4};
6 Number[] myNumber = myInts;
7
8 myNumber[0] = 3.14; //run-time error!
第8行会报错的原因是myNumber指向的是一个Integer[] 而不是Number[],对Interger赋值一个double类型的,不是协变
其实在继承中只需要注意LSP原则即可,这是不矛盾的。
对于参数,也就是前置条件,应当逆变,把前置条件范围放宽。
对于返回值,也就是后置条件,应当协变,把后置条件范围缩小。
这两者加起来,也就是规约变强,符合LSP。
LSP原则中的逆变和协变的更多相关文章
- Java中的逆变与协变
看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...
- Java中的逆变与协变(转)
看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...
- Java中的逆变与协变 专题
结论先行: PECS总结: 要从泛型类取数据时,用extends: 协变 要往泛型类写数据时,用super: 逆变 既要取又要写,就不用通配符(即extends与super都不用) 不变 List&l ...
- OOP中的逆变和协变
逆变和协变在存在于强类型语言中,尽管非常少提及.可是里面蕴含了面向对象的世界观.感谢和我一起讨论这个问题的人. 这里用了C#.Scala的语法作为演示样例.事实上逆变和协变的概念跟语言本身关系不大.事 ...
- C#中的逆变和协变
msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型. “逆变”则是指能够使用派生程度更小的类型. 解释的很正确,大致就是这样,不过不够直白. 直白的理解: “协变” ...
- Java中的逆变与协变 很直接不饶弯的讲出来了
```java 协变 extends只能new 辈分比自己低的家伙 List<? extends Number> list001 = new ArrayList<Integer> ...
- Java 逆变与协变的名词说明
最近在研究Thinking in Java的时候,感觉逆变与协变有点绕,特意整理一下,方便后人.我参考于Java中的逆变与协变,但是该作者整理的稍微有点过于概念化,我在这里简单的说一下 我对于协变于逆 ...
- Java 逆变与协变
最近一直忙于学习模电.数电,搞得头晕脑胀,难得今天晚上挤出一些时间来分析一下Java中的逆变.协变.Java早于C#引入逆变.协变,两者在与C#稍有不同,Java中的逆变.协变引入早于C#,故在形式没 ...
- .NET Core CSharp初级篇 1-8泛型、逆变与协变
.NET Core CSharp初级篇 1-8 本节内容为泛型 为什么需要泛型 泛型是一个非常有趣的东西,他的出现对于减少代码复用率有了很大的帮助.比如说遇到两个模块的功能非常相似,只是一个是处理in ...
- .NET 4.0中的泛型逆变和协变
转载自:http://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html:自己加了一些理解 随Visual Studi ...
随机推荐
- ROS-安装与开发速记
参考教程: B站视频(感谢赵老师):https://www.bilibili.com/video/BV1Ci4y1L7ZZ?p=14&spm_id_from=pageDriver 课程文件:h ...
- 第一次写,python爬虫图片,操作excel。
第一次写博客,其实老早就注册博客园了,有写博客的想法,就是没有行动,总是学了忘,忘了丢,最后啥都没有,电脑里零零散散,东找找,西看看,今天认识到写博客的重要性. 最近闲着看了潭州教育的在线直播课程,颇 ...
- QT如何安装?
Qt安装教程 OLD HELPS <oldhelps@126.com > 目录 Qt安装教程 下载 注册.登录 接受验证邮件 安装 下载 从https://download.qt.io/n ...
- [USACO12FEB]Overplanting S
洛咕 题意:在一个笛卡尔平面坐标系里(X轴向右是正方向,Y轴向上是正方向),有\(N(1<=N<=1000)\)个矩形,第\(i\)个矩形的左上角坐标是\((x1, y1)\),右下角坐标 ...
- nvim比较两个文件的不同
vim -d file1 file2 或 vimdiff file1 file2 2. 如果已经打开了文件file1,再打开另一个文件file2进行比较: :vert diffsplit file2 ...
- Jquery 如何替换html字符串中标签属性值 ??
如何利用JQuery 替换HTML字符串中的属性值呢? 如 html 字符串有很多 img标签,现在需要修改 img的src值 var html="<div style="t ...
- HDLbits——Lfsr32
//Build a 32-bit Galois LFSR with taps at bit positions 32, 22, 2, and 1. 草图 verilog描述 module top_mo ...
- Pytorch Dropout函数
Dropout layers class torch.nn.Dropout(p=0.5, inplace=False) 随机将输入张量中部分元素设置为0.对于每次前向调用,被置0的元素都是随机的. 参 ...
- 物流扫码固定式扫描相机BXT-10M 自动分拣读码器 条码识别扫码器
物流扫码固定式扫描相机BXT-10M 自动分拣读码器 条码识别扫码器 VX : orihard2014 标签: 条码识别扫码器, 自动分拣读码器, 物流扫码固定式扫描相机, 物流扫码相机
- .NET Core3.1升级.NET5 oracle连接报错
如果报以下错误 The type initializer for 'OracleInternal.ServiceObjects.OracleConnectionImpl' threw an excep ...