一、類型參數
### --- 擴充大綱
~~~ 類型參數
~~~ 泛型類、泛型函數、協變和逆變
~~~ Akka
### --- 類型參數
~~~ Scala的類型參數與Java的泛型是一樣的,
~~~ 可以在集合、類、函數中定義類型參數,進而保證程式更好的健壯性。
### --- 泛型類
~~~ 泛型類,顧名思義,其實就是在類的聲明中定義一些泛型類型,
~~~ 然後在類内部的字段或者方法,就可以使用這些泛型類型。
~~~ 使用泛型類,通常是需要對類中的某些成員,
~~~ 比如某些字段和方法中的參數或變量進行統一的類型限制,這樣可以保證程式更好的健壯性和穩定性。
~~~ 如果不使用泛型進行統一的類型限制,那麼在後期程式運作過程中難免會出現問題,
~~~ 比如傳入了不希望的類型導緻程式出問題。
~~~ 在使用泛型類的時候,比如建立泛型類的對象,隻需将類型參數替換為實際的類型即可。
~~~ Scala自動推斷泛型類型特性:直接給使用泛型類型的字段指派時,Scala會自動進行類型推斷。
### --- 泛型類的定義如下:
~~~ # 定義一個泛型類
class Stack[T1, T2, T3](name: T1) {
var age: T2 = _
var address: T3 = _
def getInfo: Unit = {
println(s"$name,$age,$address")
}
}
~~~ # 使用上述的泛型類,隻需要使用具體的類型代替類型參數即可。
object GenericityDemo {
def main(args: Array[String]): Unit = {
//建立泛型類對象
val stack = new Stack[String, Int, String]("lisi")
stack.age = 20
stack.address = "北京"
stack.getInfo
}
}
二、泛型函數
### --- 泛型函數
~~~ 泛型函數,與泛型類類似,可以給某個函數在聲明時指定泛型類型,然後在函數體内,
~~~ 多個變量或者傳回值之間,就可以使用泛型類型進行聲明,
~~~ 進而對某個特殊的變量,或者多個變量,進行強制性的類型限制。
~~~ 與泛型類一樣,你可以通過給使用了泛型類型的變量傳遞值來讓Scala自動推斷泛型的實際類型,
~~~ 也可以在調用函數時,手動指定泛型類型。
### --- 案例:卡片售賣機,可以指定卡片的内容,内容可以是String類型或Int類型
object GenericityFunction {
def getCard[T](content: T) = {
content match {
case content: Int => s"card:$content is Int "
case content: String => s"card:$content is String"
case _ => s"card:$content"
}
}
def main(args: Array[String]): Unit = {
println(getCard[String]("hello"))
println(getCard(1001))
}
}
三、程式設計實作
### --- 程式設計代碼
package yanqi.cn.part11
//定義一個泛型類
class Stack[T1, T2, T3](name: T1) {
var age: T2 = _
var address: T3 = _
def getInfo: Unit = {
println(s"$name,$age,$address")
}
}
object GenericityDemo {
def main(args: Array[String]): Unit = {
//建立泛型類的對象
val stack=new Stack[String,Int,String]("lisi")
stack.age=20
stack.address="北京"
stack.getInfo
}
}
### --- 編譯列印
D:\JAVA\jdk1.8.0_231\bin\java.exe "-javaagent:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=61763:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\JAVA\jdk1.8.0_231\jre\lib\charsets.jar;D:\JAVA\jdk1.8.0_231\jre\lib\deploy.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\dnsns.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jaccess.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\localedata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\nashorn.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunec.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\zipfs.jar;D:\JAVA\jdk1.8.0_231\jre\lib\javaws.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jce.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfr.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfxswt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jsse.jar;D:\JAVA\jdk1.8.0_231\jre\lib\management-agent.jar;D:\JAVA\jdk1.8.0_231\jre\lib\plugin.jar;D:\JAVA\jdk1.8.0_231\jre\lib\resources.jar;D:\JAVA\jdk1.8.0_231\jre\lib\rt.jar;E:\NO.Z.10000——javaproject\NO.Z.00002.Hadoop\ScalaPro\out\production\ScalaPro;D:\JAVA\scala-2.12.2\lib\scala-library.jar;D:\JAVA\scala-2.12.2\lib\scala-reflect.jar yanqi.cn.part11.GenericityDemo
lisi,20,北京
Process finished with exit code 0
四、協變和逆變
### --- 協變和逆變
~~~ Scala的協變和逆變是非常有特色的,完全解決了Java中的泛型的一大缺憾!
~~~ 舉例來說,Java中,如果有Professional是Master的子類,那麼Card[Professionnal]是不是Card[Master]的子類?答案是:不是。是以對于開發程式造成了很多的麻煩。
~~~ 而Scala中,隻要靈活使用協變和逆變,就可以解決Java泛型的問題。
~~~ 協變定義形式如:trait List[+T] {}
~~~ 當類型S是類型A的子類型時,則List[S]也可以認為是List[A}的子類型,即List[S]可以泛化為List[A],
~~~ 也就是被參數化,類型的泛化方向與參數類型的方向是一緻的,是以稱為協變(covariance)。
~~~ 逆變定義形式如:trait List[-T] {}
~~~ 當類型S是類型A的子類型,則Queue[A]反過來可以認為是Queue[S}的子類型,
~~~ 也就是被參數化類型的泛化方向與參數類型的方向是相反的,是以稱為逆變(contravariance)。
~~~ # 小結:
~~~ 如果A是B的子類,那麼在協變中,List[A]就是List[B]的子類; 在逆變中,List[A]就是List[B]的父類。
### --- 協變案例:隻有大師以及大師級别以下的名片都可以進入會場
package yanqi.cn.part11
//大師
class Master
//專家
class Professor extends Master
//講師
class Teacher
//這個是協變,Professor是Master的子類,此時Card[Profesor]也是Card[Master]的子類
class Card[+T]
object CovarianceDemo {
def enterMeet(card: Card[Master]): Unit = {
//隻有Card[Master]及其子類Card[Professor]才能進入會場。
println("歡迎進入會場!")
}
def main(args: Array[String]): Unit = {
val masterCard = new Card[Master]
val professorCard = new Card[Professor]
val teacharCard = new Card[Teacher]
enterMeet(masterCard)
enterMeet(professorCard)
//此處就會報錯
//enterMeet(teacharCard)
}
}
### --- 程式設計代碼
package yanqi.cn.part11
//大師
class Master
//專家
class Professor extends Master
//講師
class Teacher
//定義協變
//class Card[+T]
//定義逆變
class Card[-T]
object ConvarianceDemo {
def enterMeet(card: Card[Professor]): Unit = {
//隻有Card[Master]和它的子類才能進入會場
println("歡迎進入會場!")
}
def main(args: Array[String]): Unit = {
val masterCard = new Card[Master]
val professorCard = new Card[Professor]
val teacherCard = new Card[Teacher]
enterMeet(masterCard)
enterMeet(professorCard)
// enterMeet(teacherCard)
}
}
### --- 編譯列印
D:\JAVA\jdk1.8.0_231\bin\java.exe "-javaagent:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=61585:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\JAVA\jdk1.8.0_231\jre\lib\charsets.jar;D:\JAVA\jdk1.8.0_231\jre\lib\deploy.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\dnsns.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jaccess.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\localedata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\nashorn.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunec.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\zipfs.jar;D:\JAVA\jdk1.8.0_231\jre\lib\javaws.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jce.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfr.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfxswt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jsse.jar;D:\JAVA\jdk1.8.0_231\jre\lib\management-agent.jar;D:\JAVA\jdk1.8.0_231\jre\lib\plugin.jar;D:\JAVA\jdk1.8.0_231\jre\lib\resources.jar;D:\JAVA\jdk1.8.0_231\jre\lib\rt.jar;E:\NO.Z.10000——javaproject\NO.Z.00002.Hadoop\ScalaPro\out\production\ScalaPro;D:\JAVA\scala-2.12.2\lib\scala-library.jar;D:\JAVA\scala-2.12.2\lib\scala-reflect.jar yanqi.cn.part11.ConvarianceDemo
歡迎進入會場!
歡迎進入會場!
Process finished with exit code 0