协变:如果A是B的父类,在你这个泛型这个类里面,那么你这个group[A]也是group[B]的父类
class Group[+T](t : T)
val groupA:Group[A] = new Group[A](new A)
val groupB:Group[B] = groupA
逆变:如果A是B的父类,在你这个泛型这个类里面,那么你这个group[A]也是group[B]的子类
class Group[-T](t : T)
val groupB:Group[B] = new Group[A](new B)
val groupA:Group[A] = groupB
上界:如果A是B的父类,T泛型必须是A的子类
class Group[T <: A](t : T)
val groupB:Group[B] = new Group[B](new B)
val groupC:Group[C] = new Group[C](new C) //错误
下界:如果A是B的父类,A和C没有继承关系,T泛型必须是A的子类
class Group[T >: A](t : T)
val groupB:Group[B] = new Group[B](new B) //错误
val groupC:Group[C] = new Group[C](new C)
注意:当在方法中B这个东西赋值进去的时候,它会转型成A,这种情况是可行的,如把上面上界例子中
val groupB = new Group(new B) //这种情况是可以的,但是groupB不是B类型,而是A类型
协变、逆变中的上下界【里氏替换原则】
如果A是B的父类,则任何A出现的地方都可以用B来替代,然后这个程序的过程,包括它的计算等等都不变的情况下,就是里氏替换原则
class Group[+T](t : T){
def f1[T](t : T) = {}
def f2[S <: T](s : s) = {}
def f3[Z >: T](z : z) = {}
}
class Group[-T](t : T){
def f1[T](t : T) = {}
def f2[S <: T](s : s) = {}
def f3[Z >: T](z : z) = {}
}