1. 程式人生 > >Kotlin 泛型的協變和逆變

Kotlin 泛型的協變和逆變

Kotlin 泛型

Kotlin 泛型的基本語法類似於 Java ,不過出於型變安全,不支援 Java 中的<? extends T>,<?super T> 萬用字元型變約束,而是採用類似 C# 的 in,out 用於支援協變和逆變,這同時避免了處理子型別化,父類化的問題(即Java泛型中典型的List<T> 不是 List<Object>的子型別的問題);

Kotlin 對於型變的支援

kotlin 使用類似 C# 泛型的方式,將型變分為協變,逆變,分別提供in,out 關鍵字對其進行支援;協變(covariant:Foo<父類> => Foo<子類>)
協變為父類泛型型變為具體子類,Kotlin 提供in關鍵字,來代替 Java 中<? extends E> 的萬用字元語法,同時為了解決Java中泛型型變型別擦除中,所引起的型別轉換安全,Kotlin 採用了 C# 的策略,即協變型別作為消費者,只能讀取而不能寫入;逆變(contravariance:Foo<子類> => Foo<父類>)逆變為子型別型變為具體父類,Kotlin 提供 out關鍵字,來代替 Java 中<? super E> 的萬用字元語法,同樣採用了 C# 的策略,逆變型別作為生產者,只能寫入而不能讀取;這裡使用官方中文文件中的2個例子,可以很直觀地演示這個概念:
//協變過程
fun copy(from: Array<out Any>, to: Array<Any>){
    ....
}
//逆變過程
fun fill(dest: Array<in Any> , value: Array<Any>){
    .....
}
以上例子中 copy 函式為將 from 引數複製到 to 引數,from 陣列作為生產者,to陣列作為消費者,使用 in 確保逆變安全;fill 函式將 value 陣列填充到 dest 陣列,dest 陣列為消費者,value 陣列為生產者,使用 out 確保協變安全;