【转】Scala的协变和逆变

转自:http://my.oschina.net/scipio/blog/282794
一、概念

    协变和逆变是描述在集合中的多态关系与原来类型多态关系之间的关系。如果T1是T的子类,那么Container[T1]是不是Container[T]的子类呢?Variance注释允许你在类继承和多态类型之间表达下面的这些关系:

 * covariant(协变),[+T],C[T1]是 C[T]的子类

 * contravariant(逆变),[-T],C[T] 是 C[T1]的子类

 * invariant(不变),[T], C[T] 与 C[T1]不相关



●协变:covariance,将子类实例的容器赋值给基类容器的能力

● 逆变:contravariance,将超类实例的容器赋值给子类容器的能力



二、实例

1、方法里头的协变与逆变

package persia.demo
object Variance {
class Pet(val name: String){
override def toString()= name
}
class Dog(override val name: String) extends Pet(name)
def workWithPets(pets: Array[Pet]){}
/**
* 协变
* T<:Pet表示T所代表的类型派生自Pet
*/
def workWithPets2[T <: Pet](pets: Array[T]){
println("play with pets:"+pets.mkString(","))
}
/**
* 逆变
* D >:S 限定了destination目标类型D必须是Source源类型S的超类
*/
def copyPets[S,D >:S](fromDogs: Array[S],toPets: Array[D]){}
 
def main(args: Array[String]){
    //协变
    val dogs = Array(new Dog("dog1"),new Dog("dog2"))
    workWithPets2(dogs)
    //逆变
    val pets = new Array[Pet](10)
    copyPets(dogs,pets)
}
}


2、类里头的协变与逆变

package persia.demo
 
object ClassVar {
 
  def main(args: Array[String]): Unit = {
      /**
       * +T告诉scala允许协变,即
       * 在类型检查期间,让scala接收某个类型及其子类
       */
      class MyList[+T]
      var list1 = new MyList[Int]
      //不写类型,默认为MyList[Nothing]
      var list2: MyList[Any] = null
      list2 = list1
       
      /**
       * 告诉scala允许逆变
       * 即允许接收某个类型及其超类
       */
      class MyList2[-T]
      var list3 = new MyList2[Any]
      var list4: MyList2[Int] = null
      list4 = list3
  }
 
}

猜你喜欢

转载自houshangxiao.iteye.com/blog/2269923