1) 若是咱們要求函數的參數能夠接受任意類型,可使用泛型,這個類型能夠表明任意的數據類型java
2) 例如List,在建立List時,能夠傳入整型、字符串、浮點數等等任意類型。那是由於List在類定義時引用了泛型。好比在Java中:public interface List<E> extends Collection<E>ide
-要求函數
1) 編寫一個Message類this
2) 能夠構建Int類型的Message,String類型的Messagescala
3) 要求使用泛型來完成設計(說明:不能使用Any)設計
-案例演示code
object boke_demo01 { def main(args: Array[String]): Unit = { val intMessage = new IntMessage[Int](10) println(intMessage) val strMessage = new StringMessage[String]("hello") println(strMessage) } } /* 編寫一個Message類 能夠構建Int類型的Message, String類型的Message. 要求使用泛型來完成設計,(說明:不能使用Any) */ abstract class Message[T](s: T) { def get = s } class IntMessage[Int](v: Int) extends Message(v) class StringMessage[String](v: String) extends Message(v)
-要求對象
1) 定義一個函數,能夠獲取各類類型的List的中間index的值blog
2) 使用泛型完成繼承
-案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val list1 = List("hello", "Tom", "world") val list2 = List(90, 10, 23) println(midList[String](list1)) // "Tom" println(midList[Int](list2)) // 10 } /* 要求 定義一個函數,能夠獲取各類類型的 List 的中間index的值 使用泛型完成 */ def midList[E](l: List[E]): E = { l(l.length / 2) } }
-Java中上界
在Java泛型裏表示某個類型是A類型的子類型,使用extends關鍵字,這種形式叫upper bounds(上限或上界),語法以下:
<T extends A> //或用通配符的形式: <? extends A>
-Scala中上界
在Scala裏表示某個類型是A類型的子類型,也稱上界或上限,使用 <: 關鍵字,語法以下:
[T<:A] //或用通配符: [_ <: A]
-Scala中上界應用案例-要求
1) 編寫一個通用的類,能夠進行Int之間、Folat之間,等實現了Comparable接口的值直接的比較.//java.lang.Integer
2) 分別使用傳統方法和上界的方式來完成,體會上界使用的好處
3) 案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val compareInt = new CompareInt(10,40) println(compareInt.greater) // 40 //第一個用法 val commonCompare1 = new CommonCompare(Integer.valueOf(12), Integer.valueOf(36))//Int println(commonCompare1.greater) //第二個用法 val commonCompare2 = new CommonCompare(java.lang.Float.valueOf(1.6f), java.lang.Float.valueOf(2.7f))//Fl println(commonCompare2.greater) //第3種寫法使用了隱式轉換 //implicit def float2Float(x: Float): java.lang.Float = x.asInstanceOf[java.lang.Float] val commonCompare3 = new CommonCompare[java.lang.Float](12.1f, 23.1f)// println(commonCompare3.greater) } } /* 編寫一個通用的類,能夠進行Int之間、Float之間,等實現了Comparable接口的值直接的比較.//java.lang.Integer 分別使用傳統方法和上界的方式來完成,體會上界使用的好處. */ //傳統方法 class CompareInt(n1: Int, n2: Int) { //返回較大的值 def greater = if(n1 > n2) n1 else n2 } //使用上界(上限)來完成 //說明 //1. [T <: Comparable[T]] 表示T類型是Comparable 子類型 //2. 即你傳入的T類要繼承Comparable接口 //3. 這樣就可使用compareTo方法 //4. 這樣的寫法(使用上界的寫法)通用性比傳統的好 class CommonCompare[T <: Comparable[T]](obj1:T,obj2:T) { def greater = if (obj1.compareTo(obj2) > 0) obj1 else obj2 }
-Java中下界
在Java泛型裏表示某個類型是A類型的父類型,使用super關鍵字,語法以下:
<T super A> //或用通配符的形式: < ? super A>
-Scala中下界
在Scala的下界或下限,使用 >: 關鍵字,語法以下:
[T >: A] //或用通配符: [_ >: A]
-Scala中下界應用案例
//1)和Animal直系的,是Animal父類的仍是父類處理,是Animal子類的按照Animal處理(), //2)和Animal無關的,一概按照Object處理! object boke_demo01 { def main(args: Array[String]): Unit = { println("ok!") //知足下界的約束 biophony(Seq(new Earth, new Earth)).map(_.sound()) //知足下界的約束 biophony(Seq(new Animal, new Animal)).map(_.sound()) //這裏咱們不能使用上界的思路去推導,這裏是能夠運行 //1.? println("===================") biophony(Seq(new Bird, new Bird)).map(_.sound()) // // biophony(Seq(new Moon)) } //下界 def biophony[T >: Animal](things: Seq[T]) = things } class Earth { //Earth 類 def sound() { //方法 println("hello !") } } class Animal extends Earth { override def sound() = { //重寫了Earth的方法sound() println("animal sound") } } class Bird extends Animal { override def sound() = { //將Animal的方法重寫 print("bird sounds") } } class Moon { // def sound()={ //將Animal的方法重寫 // print("bird sounds") // } }
-Scala中下界的使用小結
1) 對於下界,能夠傳入任意類型
2) 傳入和Animal直系的,是Animal父類的仍是父類處理,是Animal子類的按照Animal處理
3) 和Animal無關的,一概按照Object處理
4) 也就是下界,能夠隨便傳,只是處理方式不同
5) 不能使用上界的思路來類推下界的含義
-說明:隱式轉換結合視圖界定的方式,比較兩個Person對象的年齡大小
object boke_demo01 { def main(args: Array[String]): Unit = { //使用了隱式轉換 val compareComm1 = new CompareComm(7, 23) println(compareComm1.greater) val compareComm2 = new CompareComm(Integer.valueOf(20), Integer.valueOf(30)) println(compareComm2.greater) //之前 <: 上界 val compareComm3 = new CompareComm[java.lang.Float](201.9f, 27.1f) println(compareComm3.greater) //上面的小數比較,在視圖界定的狀況下,就能夠這樣寫了 //這裏會進行隱式轉換 val compareComm4 = new CompareComm(201.9f, 360.1f) println(compareComm4.greater) } } //說明 //1. T <% Comparable[T] 說明 T是 Comparable子類型 //2. T <% Comparable[T] 和 T <: Comparable[T] 區別就是視圖界定支持隱式轉換 //3. 視圖界定不但支持之前上界的寫法,同時支持簡潔的寫法val compareComm1 = new CompareComm(1, 20) class CompareComm[T <% Comparable[T]](obj1: T, obj2: T) { def greater = if (obj1.compareTo(obj2) > 0) obj1 else obj2 }
與view bounds同樣context bounds(上下文界定)也是隱式參數的語法糖。爲了語法上的方便,引用了「上下文這個概念」
-要求:使用上下文界定+隱式參數的方式,比較兩個Person對象的年齡大小。使用Ordering實現比較
-案例演示
object boke_demo01 { //這裏我定義一個隱式值 Ordering[Person]類型 implicit val personComparetor = new Ordering[Person4] { override def compare(p1: Person4, p2: Person4): Int = p1.age - p2.age } def main(args: Array[String]): Unit = { // val p1 = new Person4("Tom", 30) val p2 = new Person4("Jack", 35) val compareComm4 = new CompareComm4(p1, p2) println(compareComm4.geatter) // "Jack", 35 val compareComm5 = new CompareComm5(p1, p2) println(compareComm5.geatter) // "Jack", 35 println("personComparetor hashcode=" + personComparetor.hashCode()) val compareComm6 = new CompareComm6(p1, p2) println(compareComm6.geatter) // "Jack", 35 } } //一個普通的Person類 class Person4(val name: String, val age: Int) { //重寫toStirng override def toString = this.name + "\t" + this.age } //方式1 //說明: //1. [T: Ordering] 泛型 //2. obj1: T, obj2: T 接受T類型的對象 //3. implicit comparetor: Ordering[T] 是一個隱式參數 class CompareComm4[T: Ordering](obj1: T, obj2: T)(implicit comparetor: Ordering[T]) { def geatter = if (comparetor.compare(obj1, obj2) > 0) obj1 else obj2 } //方式2 //方式2,將隱式參數放到方法內 class CompareComm5[T: Ordering](o1: T, o2: T) { def geatter = { def f1(implicit cmptor: Ordering[T]) = cmptor.compare(o1, o2) //返回一個數字 //若是f1返回的值>0,就返回o1,不然返回o2 if (f1 > 0) o1 else o2 } def lowwer = { def f1(implicit cmptor: Ordering[T]) = cmptor.compare(o1, o2) //返回一個數字 //若是f1返回的值>0,就返回o2,不然返回o1 if (f1 > 0) o2 else o1 } } //方式3 //方式3,使用implicitly語法糖,最簡單(推薦使用) class CompareComm6[T: Ordering](o1: T, o2: T) { def geatter = { //這句話就是會發生隱式轉換,獲取到隱式值 personComparetor //底層仍然使用編譯器來完成綁定(賦值的)工做 val comparetor = implicitly[Ordering[T]] println("comparetor hashcode=" + comparetor.hashCode()) if (comparetor.compare(o1, o2) > 0) o1 else o2 } }
1) Scala的協變(+),逆變(-),協變covariant、逆變contravariant、不可變invariant
2) 對於一個帶類型參數的類型,好比List[T],若是對A及其子類型B,知足List[B]也符合List[A]的子類型,那麼就稱爲covariance(協變),若是List[A]是List[B]的子類型,即與原來的父子關係正相反,則稱爲contravariance(逆變)。若是一個類型支持協變和逆變,則稱這個類型爲variance(可變的),不然稱爲invariance(不可變的)
3) 在Java裏,泛型類型都是invariant,好比List<String>並非List<Object>的子類型。而Scala支持,能夠在定義類型時聲明(用加號表示協變,減號表示逆變),如:trait List[+T]//在類型定義時聲明爲協變這樣會把List[String]做爲List[Any]的子類型
-說明:在這裏引入關於這個符號的說明,在聲明Scala的泛型類型時,「+」表示協變,而「-」表示逆變
1) C[+T]:若是A是B的子類,那麼C[A]是C[B]的子類,稱爲協變
2) C[-T]:若是A是B的子類,那麼C[B]是C[A]的子類,稱爲逆變
3) C[T]:不管A和B是什麼關係,C[A]和C[B]沒有從屬關係,稱爲不變
-案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val t1: Temp3[Sub] = new Temp3[Sub]("hello");//ok val t2: Temp3[Sub] = new Temp3[Super]("hello");//error val t3: Temp3[Super] = new Temp3[Sub]("hello");//error val t4: Temp3[Super] = new Temp3[Super]("hello"); //ok val t5: Temp4[Super] = new Temp4[Sub]("hello"); //ok val t6: Temp4[Sub] = new Temp4[Super]("hello"); //error val t7: Temp5[Sub] = new Temp5[Sub]("hello"); //ok val t8: Temp5[Sub] = new Temp5[Super]("hello"); //ok val t9: Temp5[Super] = new Temp5[Sub]("hello"); //error } } //協變 class Temp4[+A](title: String) { //Temp3[+A] //Temp[-A] override def toString: String = { title } } //逆變 class Temp5[-A](title: String) { //Temp3[+A] //Temp[-A] override def toString: String = { title } } //不變 class Temp3[A](title: String) { //Temp3[+A] //Temp[-A] override def toString: String = { title } } //支持協變 class Super //父類 //Sub是Super的子類 class Sub extends Super