以java为例理解协变性
来源:互联网 发布:蛮牛unity3d 编辑:程序博客网 时间:2024/05/19 06:51
以java为例理解协变性
这篇文章以java为例,解释下语言的类型系统中的几个重要概念,协变性(covariance)、逆变性(contravariance)和无关性(invariant)
在面向对象语言中由于继承的存在,安全的类型转换对于书写正确的代码至关重要。而上面几个概念就是用来描述这种类型转换的性质的。
首先,看下这几个概念的定义:
如果M和N是类型,f()表示类型转换,≤表示子类型关系,(例如M≤N,表示M是N的子类)那么:
如果M≤N 则f(M) ≤f(N) 那么 f()是协变的
如果M≤N 则f(N) ≤f(M) 那么 f()是逆变的
如果上面两种都不成立,那么f()是无关的
举个例子,首先规定如下继承规则,后面例子中不另行说明都默认有这个定义 C≤B≤A
class A{}class B extends A{}class C extends B{}
然后,规定f(x)=x[]
B[] w2 = null;A[] q1 = w2;B[] q2 = w2;C[] q3 = w2;//ERROR:编译错误Type mismatch
由上可得,B[]为A[]的子类,这样就证明数组变换具有协变性
这说明在java中,数组具有协变性的
再看个例子
class Animal{public B deal(){return null;}} class Cat extends Animal{@Overridepublic B deal(){return null;}}
Cat继承了deal()函数,deal()的返回值为A则会发生编译错误,返回为B和C则正确。这说明继承覆盖函数返回值具有协变性。
那对于继承覆盖函数的参数呢?
class Animal{void deal(B t){}} class Cat extends Animal{@Overridevoid deal(B t){}}
Cat的deal函数为A或者C都会报错,这说明继承覆盖函数的参数具有不变性。当然,去掉Override标志后,函数重载deal函数,参数写什么都无所谓,但是那样连类型转换都没有发生,就没有讨论的价值了。
几个基本的情况都清楚了,下面看下java的泛型List<?>
List<B> t1 = null;List<B> t2 = null;t1 = t2;
很明显,t2的类型为List<A>,List<C>都会报编译错误
这说明List<>和数组不同,具有不变性!
所幸,对于这种尴尬的情况,java提供了通配符这一功能,来解决这一问题,extends和super,前一个代表了协变性,后一个代表逆变性。
List<A>t1 = null; List<B>t2 = null; List<C>t3 = null; List<?extends B> t = null; t = t1;//ERROR t = t2; t = t3; List<A>t1 = null; List<B>t2 = null; List<C>t3 = null; List<?super B> t = null; t = t1; t = t2; t = t3;//ERROR
- 以java为例理解协变性
- Java 协变性 逆变性
- Java 协变性 逆变性 学习笔记
- java 协变性 逆变性 学习笔记
- java 协变性和兼容性
- java里的协变性与逆变性
- 深入理解java String 对象的不可变性
- 字符 深入理解java String 对象的不可变性
- Java基本学习:数组--协变性
- 关于Java协变性的思考
- 深入理解泛型(二) 协变性和逆变性
- java事务大总结(一) 先理解数据库的事务以mysql为例
- C#的协变性和逆变性
- C#中的协变性与逆变性
- Java基础:泛型及其擦除性、不可协变性
- Java基础:泛型及其擦除性、不可协变性
- Java基础:泛型及其擦除性、不可协变性
- Java环境搭建,以win10为例
- Ubuntu创建快捷方式
- 【菜鸟学习Linux】-第三章- Linux环境搭建-使用VMware9安装Ubuntu 12.04系统
- [译]儿时梦想成真: Spine背后的故事
- 准备开始创业
- 【G-BLASTN 1.0正式发布】
- 以java为例理解协变性
- MPEG-2视频编码技术漫谈
- 前还算是个新鲜事物
- H264基本概念--【转】图像、帧、片、NALU
- Vim史上最全面的知识点总结
- NAND write: '$filesize' is not a number
- 指针的错误赋值
- UVAlive 2911 Maximum(贪心)
- 【菜鸟学习Linux】-第二章- Linux环境搭建-使用VMware9联网设置”