Scala学习记录「1」

协变、逆变

Posted by Jie on February 15, 2017

最近看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的原因与协变类似。