美文网首页
什么是协变, 逆变?

什么是协变, 逆变?

作者: 随风风筝 | 来源:发表于2019-02-19 11:04 被阅读0次

好的软件的作用是让复杂的东西看起来简单。

java中协变跟逆变是对泛型类的继承关系的表述.
如:
List<Number>List<Integer> 之间是没有继承关系的.
但是直观上会觉得, IntegerNumber 的子类, 所以List<Integer> 应是List<Number> 的子类.
如果想要这种效果, 就要用协变.
List<? extends Number> 这样 List<Integer> 就能成为List<? extends Number> 子类, 也就是可以赋值

List<Integer>b = new ArrayList<>();
List<? extends Number> a = b;

这里如果你想要相反的效果, 则用逆变,List<? super Number> 这样继承关系就会相反.

那么什么时候用协变,逆变?
协变主要是用在函数的返回值上,逆变用在函数参数上,这样的规则也就能遵循里氏替换原则.
Function, 在这里R 作为函数的返回值, 所以这个泛型要协变, 而T用在函数的参数上所以要用逆变

Function<? super Dog,? extends Animal> f1;

这里举个例子
假设有以下继承关系:
车 > 轿车 > 标准轿车 > 高级轿车
现在有一个人声称自己能修理所有的标准轿车, 所以发出了以下公告:

修理(List<标准轿车> cars)

假设我现在有List<轿车>List<高级轿车>
那么这个人到底能修理哪个呢? 从上面的函数声明来看都不可以.

再来看看这个人的声明
他说能够修理所有标准轿车
那么因为标准轿车扩展了轿车, 所以如果能够修理标准轿车, 那么应当可以修理轿车
所以这个函数应当可以接受所有标准轿车的父类
也就是说 List<轿车> 能够传入 以List<标准轿车>为参数的函数
换句话说 List<轿车>List<标准轿车>的子类, 这样才能传入参数
所以上面的公告要用逆变, 改成如下:

修理(List<? super 标准轿车> cars)

也许也不会有人想把自己的高级轿车交给这家伙.
以此类推, 函数的返回值应当用协变, 这样既能满足里氏替换原则

相关文章

  • Java中的逆变与协变

    什么是逆变与协变 协变(Covariance) 如果B是A的子类,并且F(B)也是F(A)的子类,那么F即为协变 ...

  • 协变和逆变

    Java的泛型只有通配符?和extends、super,没有语法上的协变和逆变。 什么是协变和逆变? 在混合OO和...

  • Kotlin 泛型协变与逆变的理解

    协变与逆变定义 逆变与协变用来描述类型转换后的继承关系 协变:如果 A 是 B 的子类型,并且Generic 也...

  • Flow中对逆变和协变的处理

    协变逆变不变的解释 协变:f(Employee) extend f(Person) 逆变:f(Person) ...

  • Java中的桥接方法与泛型的逆变和协变

    泛型的协变和逆变是什么?对应于Java当中,协变对应的就是,而逆变对应的就是

  • JAVA泛型与类型安全

    1. 基础泛型 2. 协变与逆变与不变 协变 简单来说即: Java中的数组是协变的 逆变与协变相对,逆转了类型关...

  • Scala 通俗易懂 ---- 协变、逆变、不变

    协变、逆变、不变 Scala 语言中协变、逆变、不变是指拥有泛型的类型,在声明和赋值时的对应关系 协变:声明时泛型...

  • 什么是协变, 逆变?

    好的软件的作用是让复杂的东西看起来简单。 java中协变跟逆变是对泛型类的继承关系的表述.如:List

  • Scala 类型系统(1)

    协变逆变引入原因 协变和逆变主要是用来解决参数化类型的泛化问题。我的理解是解决Scala高阶函数参数引入。 定义协...

  • kotlin 泛型

    1.协变 逆变 不变

网友评论

      本文标题:什么是协变, 逆变?

      本文链接:https://www.haomeiwen.com/subject/mblxyqtx.html