由于擦拭法的原因,泛型中的的元素类型即使有继承关系,对应的泛型也没有相应的继承关系。
示例
class Pair[T](a:T)
object Pair {
def main(args: Array[String]): Unit = {
val p1 = new Pair("hello")
// 编译报错,无法将p1转换为p2
//hello->String
//String->AnyRef String有个父类型AnyRef
//但是Pair[String]不是Pair[AnyRef]的子类型 报错
val p2:Pair[AnyRef] = p1
println(p2)
}
}
- AnyRef是String的父类,但是Pair[AnyRef]和Pair[String]直接没有继承关系
scala中引入了协变 逆变和非变的概念
协变
class Pair[+T],这种情况是协变。类型B是A的子类型,Pair[B]可以认为是Pair[A]的子类型。这种情况,参数化类型的方向和类型的方向是一致的。
逆变
class Pair[-T],这种情况是逆变。类型B是A的子类型,Pair[A]反过来可以认为是Pair[B]的子类型。这种情况,参数化类型的方向和类型的方向是相反的。
非变
class Pair[T]{},这种情况就是非变(默认),类型B是A的子类型,Pair[A]和Pair[B]没有任何从属关系,这种情况和Java是一样的。
示例
class Super
class Sub extends Super
//非变
class Temp1[A](title: String)
//协变
class Temp2[+A](title: String)
//逆变
class Temp3[-A](title: String)
object Covariance_demo {
def main(args: Array[String]): Unit = {
val a = new Sub()
// 没有问题,Sub是Super的子类
val b:Super = a
// 非变
val t1:Temp1[Sub] = new Temp1[Sub]("测试")
// 报错!默认不允许转换
// val t2:Temp1[Super] = t1
// 协变
val t3:Temp2[Sub] = new Temp2[Sub]("测试")
val t4:Temp2[Super] = t3
// 逆变
val t5:Temp3[Super] = new Temp3[Super]("测试")
val t6:Temp3[Sub] = t5
}
}
总结
- C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。
- C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。
- C[T]: 无论A和B是什么关系,C[A]和C[B]没有从属关系。