个人随笔
目录
Scala学习之路 (九)Scala的协变和逆变
2019-12-20 23:03:47

Scala中协变和逆变主要作用是用来解决参数化类型的泛化问题。由于参数化类型的参数(参数类型)是可变的,当两个参数化类型的参数是继承关系(可泛化),那被参数化的类型是否也可以泛化呢?在Java中这种情况下是不可泛化的,然而Scala提供了三个选择,即协变、逆变和非变,解决了参数化类型的泛化问题。

协变和逆变

在Scala语言中,协变和逆变到处可见。如List,Queue等属于协变和逆变的一种。

协变和逆变使用“+”,“-”差异标记。当我们定义一个协变类型List[+A]时,List[Child]可以是List[Parent]的子类型,当我们定义一个逆变类型List[-A]时,List[Child]可以是List[Parent]的父类型。

+B是B的超集,叫协变+B是B的超集,叫协变

-A是A的子集,叫逆变

假设有参数化特质List,那么可以有三种定义。如下所示:

(1) trait List [T]{}

非变。这种情况下,当类型S是类型A的子类型,则List [S]不可以认为是List [A]的子类型或父类型,这种情况和Java是一样的。

(2) trait List [+T]{}

协变。如果S extends A (S为子类型,A为父类型),则List [S]为子类型,List [A]为父类型 S <: A => List [S] <: List [A]。

(3) trait List [-T]{}

逆变。如果S extends A (S为子类型,A为父类型),则List [S]为父类型,List [A]为子类型,和协变互逆S <: A => Queue[S] >: Queue[A]。

那么,在Scala中如何定义协变逆变类呢,举例如下。

  1. package first
  2. //协变逆变测试
  3. object CovariantAndContravariantDemo {
  4. def main(args: Array[String]): Unit = {
  5. //不变
  6. //定义一个方法,返回值为Invariant[Child]
  7. def inv1:Invariant[Child]=new Invariant[Child]()
  8. // 会报错:因为Invariant是不变的,所以虽然Parent是Child的父类也不能赋值
  9. def inv2:Invariant[Parent] = inv1
  10. //协变
  11. //定义一个方法,返回值为Covariant[Child]
  12. def cov1:Covariant[Child]=new Covariant[Child]()
  13. //不会报错:Covariant是协变的,所以当Child是Parent的子类的时候,Covariant[Child]
  14. //也可以是Covariant[Parent]的子类。【这就是协变的强大之处,java没有这个功能】
  15. def cov2:Covariant[Parent] = cov1
  16. //逆变
  17. //定义一个方法,返回值为Cotravariant[Parent]
  18. def cot1:Cotravariant[Parent]=new Cotravariant[Parent]()
  19. //不会报错:Cotravariant是逆变的,所以当Child是Parent的子类的时候,Cotravariant[Parent]
  20. //也可以是Cotravariant[Child]的子类型,赋值不会报错。
  21. def cot2:Cotravariant[Child] = cot1
  22. }
  23. }
  24. /**
  25. * 定义一个不可变的类
  26. */
  27. class Invariant[T]{}
  28. /**
  29. * 定义一个协变的类
  30. */
  31. class Covariant[+T]{}
  32. /**
  33. * 定义一个逆变的类
  34. */
  35. class Cotravariant[-T]{}
  36. /**
  37. * 定义一个父类
  38. */
  39. class Parent{}
  40. /**
  41. * 定义一个子类
  42. */
  43. class Child extends Parent{}

相信我上面的例子很详细!

 348

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2