【转】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
  }
 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值