當我們在 kotlin 中定義泛型時,我們會發現它需要使用到in
和out
兩個關鍵字來定義。從形式上來講,這是一種定義「逆變」和「協變」的方式。
那啥叫逆變?啥叫協變?可以參考下維基百科的定義:協變與逆變
out(協變)
如果泛型類只將泛型型別作為函式的返回(輸出),那麼使用 out:
inte***ce production
可以稱之為生產類/介面,因為它主要是用來生產(produce)指定的泛型物件。因此,我們可以簡單地這樣記憶:
produce = output = out
in(逆變)
如果泛型類只將泛型型別作為函式的入參(輸入),那麼使用 in:
inte***ce consumer
可以稱之為消費者類/介面,因為它主要是用來消費(consume)指定的泛型物件。因此我們可以簡單地這樣記憶:
consume = input = in
invariant(不變)
如果泛型類既將泛型型別作為函式引數,又將泛型型別作為函式的輸出,那麼既不用 out 也不用 in:
inte***ce productionconsumer
舉個例子,我們定義下漢堡類物件,它是一種快餐,也是一種食物。
open class food
open class fastfood : food()
class burger : fastfood()
漢堡生產者
根據上面定義的生產(production)介面,我們可以進一步擴充套件它們來生產食物、快餐和漢堡:
class foodstore : production
}class fastfoodstore : production
}class inoutburger : production
}
現在,我們可以這樣賦值:
val production1 : production= foodstore()
val production2 : production= fastfoodstore()
val production3 : production= inoutburger()
顯然,漢堡商店屬於快餐商店,也屬於食物商店。
因此,對於 out 型別,我們能夠將使用子類泛型的物件賦值給使用父類泛型的物件。如果我們修改如下,那麼就會出錯了,因為食物或快餐商店是可以生產漢堡,但不一定僅僅生產漢堡:
val production1 : production= foodstore() // error
val production2 : production= fastfoodstore() // error
val production3 : production= inoutburger()
漢堡消費者
根據上面定義的消費(consumer)介面,我們可以進一步擴充套件它們來消費食物、快餐和漢堡:
class everybody : consumer
}class modernpeople : consumer
}class american : consumer
}
我們可以將人類、現代人、美國人指定為漢堡消費者,所以可以這樣賦值:
val consumer1 : consumer= everybody()
val consumer2 : consumer= modernpeople()
val consumer3 : consumer= american()
不難理解,漢堡的消費者可以是美國人,也可以是現代人,更可以是人類。
因此,對於 in 泛型,我們能夠將使用父類泛型的物件賦值給使用子類泛型的物件。反之,如果我們修改如下,就會出現錯誤,因為漢堡的消費者不僅僅是美國人或現代人。
val consumer1 : consumer= everybody()
val consumer2 : consumer= modernpeople() // error
val consumer3 : consumer= american() // error
Kotlin 泛型中的 in 和 out
簡評 在 kotlin 中使用泛型你會注意到其中引入了 in 和 out,對於不熟悉的開發者來說可能有點難以理解。從形式上講,這是一種定義逆變和協變的方式,這篇文章就來講講怎麼來理解和記住它們。out 協變 如果你的類是將泛型作為內部方法的返回,那麼可以用 out inte ce productio...
Kotlin 泛型中的 in 和 out
簡評 在 kotlin 中使用泛型你會注意到其中引入了 in 和 out,對於不熟悉的開發者來說可能有點難以理解。從形式上講,這是一種定義 逆變和協變的方式,這篇文章就來講講怎麼來理解和記住它們。in out 怎麼記?out 協變 如果你的類是將泛型作為內部方法的返回,那麼可以用 out inte ...
Kotlin筆記之泛型(一)
泛型類和函式 型別引數約束 泛型允許定義帶型別形參的型別,當這種型別的例項被建立出來的時候,型別形參被替換成稱為型別實參的具體型別 例項 原始碼listof函式宣告 funlistof vararg elements t list val list listof hello world 編譯器推導 ...