spark筆記之Scala中的協變、逆變、非變

1.1. 協變、逆變、非變介紹ide

協變和逆變主要是用來解決參數化類型的泛化問題。Scala的協變與逆變是很是有特點的,徹底解決了Java中泛型的一大缺憾;舉例來講,Java中,若是有 A是 B的子類,但 Card[A] 卻不是 Card[B] 的子類;而 Scala 中,只要靈活使用協變與逆變,就能夠解決此類 Java 泛型問題;scala

因爲參數化類型的參數(參數類型)是可變的,當兩個參數化類型的參數是繼承關係(可泛化),那被參數化的類型是否也能夠泛化呢?Java中這種狀況下是不可泛化的,然而Scala提供了三個選擇,即協變(「+」)、逆變(「-」)和非變。code

下面說一下三種狀況的含義,首先假設有參數化特徵Queue,那它能夠有以下三種定義。繼承

(1)  trait Queue[T] {}it

這是非變狀況。這種狀況下,當類型B是類型A的子類型,則Queue[B]與Queue[A]沒有任何從屬關係,這種狀況是和Java同樣的。ast

(2) trait Queue[+T] {} 
        這是協變狀況。這種狀況下,當類型B是類型A的子類型,則Queue[B]也能夠認爲是Queue[A]的子類型,即Queue[B]能夠泛化爲Queue[A]。也就是被參數化類型的泛化方向與參數類型的方向是一致的,因此稱爲協變。class

(3)   trait Queue[-T] {}泛型

這是逆變狀況。這種狀況下,當類型B是類型A的子類型,則Queue[A]反過來能夠認爲是Queue[B]的子類型。也就是被參數化類型的泛化方向與參數類型的方向是相反的,因此稱爲逆變。object

1.2. 協變、逆變、非變總結總結

Ø C[+T]:若是A是B的子類,那麼C[A]是C[B]的子類。

Ø C[-T]:若是A是B的子類,那麼C[B]是C[A]的子類。

Ø C[T]: 不管A和B是什麼關係,C[A]和C[B]沒有從屬關係。

1.3. 案例

package cn.itcast.scala.enhance.covariance

 

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]) {

    //支持協變 Temp1[Sub]仍是Temp1[Super]的子類

    val t1: Temp1[Super] = new Temp1[Sub]("hello scala!!!")

    //支持逆變 Temp1[Super]是Temp1[Sub]的子類

    val t2: Temp2[Sub] = new Temp2[Super]("hello scala!!!")

    //支持非變 Temp3[Super]與Temp3[Sub]沒有從屬關係,以下代碼會報錯

    //val t3: Temp3[Sub] = new Temp3[Super]("hello scala!!!")

 

//val t4: Temp3[Super] = new Temp3[Sub]("hello scala!!!")

    println(t1.toString)

    println(t2.toString)

  }

}
相關文章
相關標籤/搜索