1 package com.dtspark.scala.basics 2 3 /** 4 * 1,scala的類和方法、函數都可以是泛型。 5 * 6 7 * 2,關於對類型邊界的限定分為上邊界和下邊界(對類進行限制) 8 * 上邊界:表達了泛型的類型必須是"某種類型"或某種類型的"子類",語法為“<:”, 9 * 下邊界:表達了泛型的類型必須是"某種類型"或某種類型的"父類",語法為“>:”, 10 * 11 12 * 3, "<%" :view bounds可以進行某種神秘的轉換,把你的類型在沒有知覺的情況下轉換成目標類型, 13 * 其實你可以認為view bounds是上下邊界的加強和補充,語法為:"<%",要用到implicit進行隱式轉換(見下面例子) 14 * 15 16 * 4,"T:classTag":相當於動態類型,你使用時傳入什么類型就是什么類型,(spark的程序的編譯和運行是區分了Driver和Executor的,只有在運行的時候才知道完整的類型信息) 17 * 語法為:"[T:ClassTag]"下面有列子 18 * 19 20 * 5,逆變和協變:-T和+T(下面有具體例子)+T可以傳入其子類和本身(與繼承關系一至)-T可以傳入其父類和本身(與繼承的關系相反), 21 * 22 23 * 6,"T:Ordering" :表示將T變成Ordering[T],可以直接用其方法進行比大小,可完成排序等工作 24 */ 25 26 class Person(val name:String){ 27 def talk(person:Person){ 28 println(this.name+" speak to "+person.name) 29 } 30 } 31 32 class Worker(name:String)extends Person(name) 33 34 class Dog(val name:String) 35 36 37 38 39 //注意泛型用的是[] 40 class Club[T<:Person](p1:T,p2:T){//"<:"必須是person或person的子類 41 def comminicate = p1.talk(p2) 42 } 43 44 45 class Club2[T<%Person](p1:T,p2:T){ 46 def comminicate = p1.talk(p2) 47 } 48 49 class Engineer 50 class Expert extends Engineer 51 //如果是+T,指定類型為某類時,傳入其子類或其本身 52 //如果是-T,指定類型為某類時,傳入其父類或其本身 53 class Meeting[+T]//可以傳入T或T的子類 54 55 class Maximum[T:Ordering](val x:T,val y:T){ 56 def bigger(implicit ord:Ordering[T])={ 57 if(ord.compare(x, y)>0)x else y 58 } 59 } 60 61 object HelloScalaTypeSystem { 62 def main(args: Array[String]): Unit = { 63 val p= new Person("Spark") 64 val w= new Worker("Scala") 65 new Club(p,w).comminicate 66 67 //"<%"的列子 68 //只是提供了一個轉換的方法,在遇到<%時會調用看dog是否被轉換了。 69 implicit def dog2Person(dog:Dog)=new Person(dog.name) 70 val d = new Dog("dahuang") 71 //注意必須強制類型轉換,implicit中雖然是將dog隱式轉換成person, 72 //但是其實是對象擦除,變成了object,所以還要強制類型轉換成person后才能使用 73 //用[person]強制轉換 74 new Club2[Person](p,d).comminicate 75 76 //-T +T例子,下面的participateMeeting方法指定具體是什么泛型 77 val p1=new Meeting[Engineer] 78 val p2=new Meeting[Expert] 79 participateMeeting(p1) 80 participateMeeting(p2) 81 // T:Ordering 的例子 82 println(new Maximum(3,5).bigger) 83 println(new Maximum("Scala","Java").bigger) 84 85 86 87 } 88 //這里指定傳入的泛型具體是什么 89 def participateMeeting(meeting:Meeting[Engineer])= println("welcome") 90 91 }
T:ClassTag的例子(根據輸入動態定義)
命令行代碼:
scala> import scala.reflect.ClassTag import scala.reflect.ClassTag scala> def mkArray[T: ClassTag](elems: T*) = Array[T](elems: _*) mkArray: [T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T] scala> mkArray(1,2,3) res1: Array[Int] = Array(1, 2, 3) scala> mkArray("ss","dd") res2: Array[String] = Array(ss, dd)
scala> mkArray(1,"dd") res2: Array[Any] = Array(1, dd)