Kotlin泛型

一、泛型

Kotlin 中的類也可以有類型參數:

class Box<T>(t: T) {
    var value = t
}

val box1: Box<Int> = Box(1)

//類型參數可以推斷出來,例如從構造函數的參數或者從其他途徑,允許省略類型參數:
val box2 = Box(1)

二、型變

聲明處型變(declaration-site variance)與類型投影(type projections)。

1.java通配符

  • 上邊界通配限定符,讓 Collection<? extends Object>是 Collection<String>的超類
  • 下邊界通配限定符,讓List<? super String> 是 List<Object> 的?個超類

2.聲明處型變

聲明處型變:在類型參數聲明處提供。這與 Java 的使用處型變相反。
out 修飾符:標注 Source 的類型參數 T 來確保它僅從 Source<T> 成員中返回(生產),并從不被消費。

interface Source<out T> {
    fun nextT(): T
}

fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs // 這個沒問題,因為 T 是?個 out-參數
}

in修飾符:它使得?個類型參數逆變:只可以被消費而不可以被生產。逆變類型的?個很好的例子是 Comparable :

interface Comparable<in T> {
    operator fun compareTo(other: T): Int
}

fun demo(x: Comparable<Number>) {
    x.compareTo(1.0)                // 1.0 擁有類型 Double,它是 Number 的?類型
    val y: Comparable<Double> = x   // 因此,我們可以將 x 賦給類型為 Comparable <Double> 的變量 
}

三、類型投影

1.使用處型變:類型投影

val ints: Array<Int> = arrayOf(1, 2, 3) 
val any = Array<Any>(3) { "" } 
copy(ints, any)

fun copy(from: Array<out Any>, to: Array<Any>) { …… }

類型投影: from 不僅僅是?個數組,而是?個受限制的(投影的)數組,只可以調用返回類型為類型參數 T 的方法,如上,這意味著我們只能調用 get() 。這就是我們的使用處型變的用法, 并且是對應于 Java 的 Array<? extends Object> ,但使用更簡單些的方式。
in 投影?個類型:

fun fill(dest: Array<in String>, value: String) { …… }

Array<in String> 對應于 Java 的 Array<? super String> ,也就是說,你可以傳遞?個 CharSequence 數組或?個 Object 數組給 fill() 函數。

2.星投影

對類型參數一無所知,但仍然希望以安全的方式使用它。定義泛型類型的投影,該泛型類型的每個具體實例化將是該投影的子類型。 Kotlin 星投影語法:

  • 對于 Foo <out T : TUpper> ,其中 T 是?個具有上界 TUpper 的協變類型參數,Foo <> 等價于 Foo <out TUpper> 。這意味著當 T 未知時,你可以安全地從 Foo <> 讀取 TUpper 的值。
  • 對于 Foo <in T> ,其中 T 是?個逆變類型參數,Foo <> 等價于 Foo <in Nothing> 。這意味著當 T 未知時,沒有什么可以以安全的?式寫? Foo <> 。
  • 對于 Foo <T : TUpper> ,其中 T 是?個具有上界 TUpper 的不型變類型參數,Foo<*> 對于讀取值 時等價于 Foo<out TUpper> ?對于寫值時等價于 Foo<in Nothing>
    果泛型類型具有多個類型參數,則每個類型參數都可以單獨投影:
  • Function<*, String> 表示 Function<in Nothing, String>
  • Function<Int, *> 表示 Function<Int, out Any?>
  • Function<*, *> 表示 Function<in Nothing, out Any?> 。

四、泛型函數

不僅類可以有類型參數。函數也可以有。類型參數要放在函數名稱之前:

fun <T> singletonList(item: T): List<T> ?{
    // ……
}

fun <T> T.basicToString(): String { // 擴展函數
    // ……
}

五、泛型約束

能夠替換給定類型參數的所有可能類型的集合可以由泛型約束限制。

1.上界

約束類型是與 Java 的 extends 關鍵字對應的 上界,冒號之后指定的類型是上界:只有 Comparable<T> 的?類型可以替代 T

fun <T : Comparable<T>> sort(list: List<T>) { …… }

默認的上界(如果沒有聲明)是 Any? 。在尖括號中只能指定?個上界。如果同?類型參數需要多個上界,我們需 要?個單獨的 where-子句:

fun <T> copyWhenGreater(
    list: List<T>,
    threshold: T
): List<String> where T : CharSequence, T : Comparable<T> {
    return list.filter { it > threshold }.map { it.toString() }
}

六、類型擦除

Kotlin 為泛型聲明用法執行的類型安全檢測僅在編譯期進行。運行時泛型類型的實例不保留關于其類型實參的任何信息。其類型信息稱為被擦除。例如,Foo<Bar> 與 Foo<Baz?> 的實例都會被擦除為 Foo<*>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,748評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,165評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,595評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,633評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,435評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,943評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,035評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,175評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,713評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,599評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,788評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,303評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,034評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,412評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,664評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,408評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,747評論 2 370

推薦閱讀更多精彩內容

  • Kotlin 中也有泛型的概念,和 Java 中的類似,但又不盡相同,一起來認識 Kotlin 中的泛型吧。 一、...
    SheHuan閱讀 28,454評論 7 24
  • 轉載文章,出處: https://blog.kotliner.cn/2017/06/26/kotlin-gener...
    _10_01_閱讀 702評論 0 0
  • 建議先閱讀我的上一篇文章 -- Java 泛型 和 Java 泛型一樣,Kotlin 泛型也是 Kotlin 語言...
    JohnnyShieh閱讀 6,510評論 1 26
  • 與Java一樣,Kotlin也支持泛型,為類型安全提供保證,消除類型強轉的煩惱 創建類的實例時我們需要指定類型參數...
    郎官人閱讀 1,242評論 0 0
  • 與 Java 類似,Kotlin 中的類也有類型參數: 一般來說,要創建這樣類的實例,我們需要提供類型參數: 但是...
    numqin閱讀 388評論 1 3