泛型介紹:泛型用於指定方法或類能夠接受任意類型參數,參數在實際使用時才被肯定,泛型能夠有效 地加強程序的適用性,使用泛型可使得類或方法具備更強的通用性。泛型的典型應用場景 是集合及集合中的方法參數。
泛型方法:指定方法能夠接受任意類型參數。
泛型類:指定類能夠接受任意類型參數。
例: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) {}
類型變量界定是指在泛型的基礎上,對泛型的範圍進行進一步的界定,從而縮小泛型的具體範圍。
例: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 } }
類型變量界定創建在類繼承的層次上,但有時候這種限定不能知足實際要求,若是但願跨越類繼承層次結構時,可使用視圖界定來實現,原理是經過隱式轉換來實現。
隱含參數和方法也能夠定義隱式轉換,稱做視圖。視圖的綁定從另外一個角度看就是 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]]使用<:的話,在運行的時候會報錯
由於:在類型變量界定的使用,默認的只能界定的類的是繼承體系中的一員才成立,若是是使用隱式轉換的方式默認不成立。上面代碼: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
在指定泛型類型時,有時須要界定泛型類型的範圍,而不是接收任意類型。好比,要求某個 泛型類型,必須是某個類的子類,這樣在程序中就能夠放心的調用父類的方法,程序才能正 常的使用與運行。此時,就可使用上下邊界 Bounds 的特性; Scala 的上下邊界特性容許泛型類型是某個類的子類,或者是某個類的父類。
U>:T這是類型下界的定義,也就是 U 必須是類型 T 的父類(或自己,本身也能夠認爲是本身的父 類)。
S<:T這是類型上界的定義,也就是 S 必須是類型 T 的子類(或自己,本身也能夠認爲是本身的子 類)。
上界:對象
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) ={ } }
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)。接口