最近看Spark源码,发现协变、逆变不是很理解. 做了几个实验加强理解.
实验一
scala> class Test[+T](var a: T)
<console>:11: error: covariant type T occurs in contravariant position in type T of value a_=
class Test[+T](var a: T)
scala> class Test[+T](val a: T)
defined class Test
可以看到协变定义的时候,变量a只能定义为不可变。
原因如下:
val test1 = new Test[String]
val test2 : Test[Any] = test1
test2.list = List[Any]()
//test2.a其实是String 如果允许改变,就能将Any赋值给String
实验二
scala> class Test[-T](var a: T)
<console>:11: error: contravariant type T occurs in covariant position in type => T of method a
class Test[-T](var a: T)
^
scala> class Test[-T](val a: T)
<console>:11: error: contravariant type T occurs in covariant position in type => T of value a
class Test[-T](val a: T)
同样,逆变不允许内部变量定义为T,因为如果这个定义成立, 那么Test[Any] 是Test[String]的子类,Any能赋值给String。
逆变使用情况
逆变不能直接赋值,但可以根据反函数,可以赋给参数(函数参数)
scala> class Test[-T](val f: T => String)
defined class Test
scala> val test: Test[String] = new Test((a: Any) => a.toString)
test: Test[String] = Test@731f8236
f不能定义为var的原因与协变类似。