Scala的泛型

Scala的泛型

泛型介紹:泛型用於指定方法或類可以接受任意類型參數,參數在實際使用時才被確定,泛型可以有效 地增強程序的適用性,使用泛型可以使得類或方法具有更強的通用性。泛型的典型應用場景 是集合及集合中的方法參數。
泛型方法:指定方法可以接受任意類型參數。
泛型類:指定類可以接受任意類型參數。
例:

object GenericTypeTest01 {
def main(args: Array[String]): Unit = {
println(new Student11[String,Int]("黃渤",33).name)
println(new Student12[String,Int]("zs",18).name)
println(new Student22[String,Int]("zs",8).age)
  }
}
class Student12[T,S](var name:T,var age:S){}
class Student11[T,S](var name:T, var age:S){}
class Person11[T](var name:T)
class Student22[T,S](name:T,var age:S) extends Person11(name) {}

 1. scala類型變量界定

  類型變量界定是指在泛型的基礎上,對泛型的範圍進行進一步的界定,從而縮小泛型的具體範圍。
例:

object Test01 {
  def main(args: Array[String]): Unit = {
    var generic=new Generic
    val result: Int = generic.compare("aa","bb")
  }
}
class Generic{
  /**
    *T<:Comparable 表示compare方法中如果輸入的類型處於Comparable類對應的繼承體系中,則是合法的,否則編譯不通過
    * 作用是:當調用泛型的方法是,但是不知道這個泛型是否有這個方法,此時使用泛型的類型變量界定,縮寫範圍,使得,泛型中有這個方法
    */
  def compare[T<:Comparable[T]](first:T,second:T)={
    val result=if(first.compareTo(second)>0) 1 else 0
    result
  }
}

 2. scala視圖界定

  類型變量界定建立在類繼承的層次上,但有時候這種限定不能滿足實際要求,如果希望跨越類繼承層次結構時,可以使用視圖界定來實現,原理是通過隱式轉換來實現。
  隱含參數和方法也可以定義隱式轉換,稱作視圖。視圖的綁定從另一個角度看就是 implicit 的轉換。其實視圖的綁定就是爲了更方便的使用隱式轉化,視圖界定利用<%符號來實現。
例:

object Test01 {
  def main(args: Array[String]): Unit = {
    var ann1 = new Animals("zs", "18")
    var ann2 = new Animals("zs", 18)
  }
}
case class Animals[T, S <: Comparable[S]](var name: T, var age: S)

此時如果在[T, S <: Comparable[S]]使用<:的話,在運行的時候會報錯
Scala的泛型
因爲:在類型變量界定的使用,默認的只能界定的類的是繼承體系中的一員才成立,如果是使用隱式轉換的方式默認不成立。上面代碼:String類繼承了Comparable,但是Int沒有繼承Comparable,只是隱式的將Int轉換成了RichInt,RichInt繼承了Comparable,所以此處出現了錯誤。
如果想隱式轉換也可以通過泛型的話可以:

object Test01 {
  def main(args: Array[String]): Unit = {
    var ann1 = new Animals("zs", "18")
    var ann2 = new Animals("zs", 18)
  }
}
case class Animals[T, S <% Comparable[S]](var name: T, var age: 

利用<%號對泛型 S 進行限定,它的意思是 S 可以是 Comparable 類繼承層次結構中實現了 Comparable 接口的類,也可以是能夠經過隱式轉換得到的實現了 Comparable 接口的類

 3. scala上界下界

  在指定泛型類型時,有時需要界定泛型類型的範圍,而不是接收任意類型。比如,要求某個 泛型類型,必須是某個類的子類,這樣在程序中就可以放心的調用父類的方法,程序才能正 常的使用與運行。此時,就可以使用上下邊界 Bounds 的特性; Scala 的上下邊界特性允許泛型類型是某個類的子類,或者是某個類的父類。
   U>:T這是類型下界的定義,也就是 U 必須是類型 T 的父類(或本身,自己也可以認爲是自己的父 類)。
   S<:T這是類型上界的定義,也就是 S 必須是類型 T 的子類(或本身,自己也可以認爲是自己的子 類)。
Scala的泛型
上界

class Generic2{
//指定上界,T必須是Comparable的子類或者是Comparable
def compare[T<:Comparable[T]] (first:T,second:T) ={
  }
}

下界

class Generic3{
//指定下界,T必須是Comparable的父類或者是Comparable
def compare[T>:Comparable[T]] (first:T,second:T) ={
  }
}

 4. scala逆變和逆變

  • 協變
     協變定義形式如:trait List[+T]{}
     當類型 B 是類型 A 的子類型時,則 List[B]也可以認爲是 List[A}的子類型,即 List[B]可以泛化 爲 List[A]。也就是被參數化類型的泛化方向與參數類型的方向是一致的,所以稱爲協變 (covariance)
    Scala的泛型
    例:
    object Test01 {
    def main(args: Array[String]): Unit = {
    var list1:MyList[Person]=new MyList(new Person)
    var list2:MyList[Son]=new MyList(new Son)
    list1=list2
    }
    }
    class Person
    class Son extends Person
    class MyList[+T](val value:T)

    這種方式,在list中只能將子類轉化成爲父類的list,如果在轉變之後,這個list中也只能存放子類的類型對象。協變的性質:輸入的類型必須是 Son 的超類。

  • 逆變
     逆變定義形式如:trait List[-T]{}
     當類型 B 是類型 A 的子類型,則 Queue[A]反過來可以認爲是 Queue[B}的子類型。也就是被參數化類型的泛化方向與參數類型的方向是相反的,所以稱爲逆變(contravariance)。
    Scala的泛型

  • 總結
    • 協變(covariant),如果它保持了子類型序關係≦。該序關係是:子類型≦基類型。
    • 逆變(contravariant),如果它逆轉了子類型序關係。
    • 不變(invariant),如果上述兩種均不適用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章