scala在高階型別的使用中,有三種變化,分別是順變、協變及逆變,下面詳細講講它們的含義與應用。
高階型別是接受其他引數用來構造新型別的,所以又稱為「型別構造器」,用type關鍵字來定義:
// 定義高階型別
type foo[t] = function0[t]
// 宣告高階型別變數
val foo: foo[int] = () => 1
// 輸出1
println(foo())
高階型別乙個重要特點是,在引數化之前,它不是乙個完整的型別,當然也就無法例項化了。
不變是指高階型別的引數不能改變,所以,這當然是滿足型變的,完全合法,如下:
val ln: list[string] = list("yiifaa")
# 引數一致,賦值顯然是合法的
val l: list[string] = ln
協變是指把型別引數轉換為引數的父類,建立方法是型別引數前加個「+」號,無需額外操作,如下:
case
class
person[+t](username: t)
// 宣告型別變數
val yiifaa: person[string] = person("yiifaa")
val yiifee: person[any] = yiifaa
如果不加「+」號會怎樣?那就會產生型別不匹配錯誤,不能適應協變,只能「不變」了。
逆變是相對於協變而言的,就是把型別引數轉換為引數的子類,建立方法是在型別引數前加個「-」。將父類轉換為子類是存在風險的,所以還需要新增轉換函式,如下:
class
person[-t](username: t)
val yiifee: person[any] = new person("yiifaa")
// 逆變發生了
val yiifaa: person[string] = yiifee
逆變主要應用於function物件,其他地方較少。
所有的型別程式設計都必須要在編譯時確定是否合法,因為型別資訊只有在編譯時才是可知的(編譯後會丟失),最後它們的關係圖如下。
2021 03 20 泛型與逆變 協變 不變筆記
目錄 泛型與逆變 協變 不變 1.陣列是協變的 2.未使用萬用字元的泛型類是不變的 為何泛型類無法強轉 3.使用萬用字元的泛型類可逆變可協變 泛型類強轉解決方案 假設有parent son grandson三個類 class parent class son extends parent class...
認真CS丨協變 逆變 不變
賦值相容性 你可以將派生類物件的例項賦值給基類的變數,這叫做賦值相容性 class animal class dog animal class program out關鍵字指明型別引數是協變的 1 我們不將dog賦值給animal dog是factory類了,無法賦值給同級別的factory類 而是...
scala的協變和逆變分析
首先引用朋友的文章 對於函式返回值引用宣告為協變的物件定義 由於物件宣告是正向擴充套件的,實際處理型別總比宣告型別範圍精確,則返回物件必然被宣告物件相容 trait cat t val child new cat string val parent cat any child val voice a...