Scala的泛型

Scala的泛型

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

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類型變量界定

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

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 的轉換。其實視圖的綁定就是爲了更方便的使用隱式轉化,視圖界定利用<%符號來實現。
例:scala

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,因此此處出現了錯誤。
若是想隱式轉換也能夠經過泛型的話能夠:3d

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 接口的類
code

 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) ={
  }
}

下界blog

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),若是上述兩種均不適用。
相關文章
相關標籤/搜索