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 ...
随机推荐
- 用有限差分估计(Finite Difference Estimate)解决地理坐标与平面像素坐标转换过程的误差造成风场粒子向量失真问题
下载NCEP的气象场grib2数据,风场是二维的向量,包含u和v两个分量.这个用经纬度投影到像素坐标会产生误差,直接绘制效果不太对:( 通过插值计算得到风场粒子的预测数据wind = interp ...
- 大道至简读后感以及JAVA伪代码
<大道至简>这本书引用<愚公移山>一文,生动完美的诠释了编程的整个过程.在两千年前的寓言中,愚公集项目组织者.团队经理.编程人员.技术分析师等众多角色于一身.首先是原始需求的产 ...
- UML各种图实践题
1. 用状态图描述一部电梯的运行
- mysql掉电后重启失败问题
报错 2022-12-07T01:41:02.844533Z 0 [ERROR] InnoDB: Ignoring the redo log due to missing MLOG_CHECKPOIN ...
- ObjectARX2016-2创建直线
众所周知,数据库里面包含各种数据表,而数据表里面又是各种记录,当然还有字段.AUTOCAD里面对于图形的管理也是基于图形数据库的.因此,想要在DWG里面添加一条直线,只需要做三件事: (1)打开数据表 ...
- div 自动高度
问题: 一个页面分上下二部分,上部分高度是固定不变的,要求下部分高度自动占满屏幕,如何实现? 第一感觉是准备用 JS 实现. 今天发现一个用 CSS 实现的方法 position: fixed; bo ...
- ID生成器实现方式的优缺点比较以及最优的ID生成器原理剖析
引用:https://blog.csdn.net/luoyang_java/article/details/90679456 本文的重点主要是ID发号器相关的知识,介绍了雪花算法,以及他的基本原理和实 ...
- Redis缓存之spring boot 部署
一.环境准备工作 # 1.JDK 安装与环境变量# 下载相应的jdk软件包,然后解压安装,我这里包名称为:jdk-8u102-linux-x64.tar.gz [root@localhost data ...
- Nginx+Tomcat 负载均衡配置
一.问题引入: Nginx+Tomcat 是目前主流的java web架构,如何让 nginx+tomcat 同时工作呢,也可以说如何使用 nginx 来反向代理 tomcat 后端均衡呢? 二.JA ...
- Java方法之什么是方法?
方法详解 何谓方法? System.out.println(),那么它是什么呢? 1.System:类 2.out:对象 3.println():方法 Java方法是语句的集合,它们在一起执行一个功能 ...