kotlin協(xié)變和逆變

# 協(xié)變和逆變的概念及示例

## 協(xié)變(Covariance)

協(xié)變允許使用子類型的實(shí)例代替泛型類型的實(shí)例个榕。例如,如果 `Dog` 是 `Animal` 的子類,那么 `List<Dog>` 可以被視為 `List<Animal>` 的一個特化版本封恰。

### 示例

假設(shè)我們有一個函數(shù),它接受一個 `List<Animal>` 并打印出每個動物的名字:

```kotlin
fun printAnimalNames(animals: List<Animal>) {
    animals.forEach { println(it.name) }
}

如果某人有一個 List<Dog> 并想使用這個函數(shù)褐啡,協(xié)變使得這成為可能:

val dogs: List<Dog> = listOf(Dog("Buddy"), Dog("Max"))
printAnimalNames(dogs) // 正確使用诺舔,因?yàn)?List<Dog> 是 List<Animal> 的協(xié)變

圖解

List<Animal>
     ^
     |
List<Dog>  <-- 協(xié)變關(guān)系

逆變(Contravariance)

逆變允許使用超類型的實(shí)例代替泛型類型的實(shí)例。例如备畦,如果 DogAnimal 的子類低飒,那么 List<Animal> 可以被視為 List<Dog> 的一個泛化版本。

示例

假設(shè)我們有一個函數(shù)懂盐,它接受一個 List<Dog> 并為每只狗洗澡:

fun batheDogs(dogs: List<Dog>) {
    dogs.forEach { it.bathe() }
}

如果某人有一個 List<Animal> 并想使用這個函數(shù)褥赊,逆變在這里是不適用的:

val animals: List<Animal> = listOf(Dog(), Cat())
batheDogs(animals as List<Dog>) // 錯誤:不能直接轉(zhuǎn)換,因?yàn)椴粷M足逆變

圖解

List<Dog>
     ^
     |
List<Animal>  <-- 逆變關(guān)系(不直接支持)

星號投影(Star Projection)

星號投影允許我們忽略泛型的具體類型莉恼,它是一種特殊的協(xié)變形式拌喉。這在你需要操作泛型集合速那,但不需要關(guān)心其具體類型時非常有用。

示例

假設(shè)我們有一個函數(shù)尿背,它接受任何類型的 List<*> 并打印出元素的數(shù)量:

fun printListSize(list: List<*>) {
    println("The list has ${list.size} elements")
}

無論是 List<Dog>端仰、List<Animal> 還是任何其他類型的列表,都可以傳遞給這個函數(shù):

val dogs: List<Dog> = listOf(Dog(), Dog())
val animals: List<Animal> = listOf(Dog(), Cat())
printListSize(dogs) // 正確使用
printListSize(animals) // 也正確使用

圖解

List<*>

星號投影允許我們以一種類型安全的方式處理未知類型的集合田藐。

結(jié)論

協(xié)變和逆變提供了一種機(jī)制榆俺,使得泛型類型可以更加靈活地使用。協(xié)變允許我們使用更具體的類型作為參數(shù)坞淮,而逆變允許我們使用更一般的類型作為參數(shù)茴晋。然而,逆變需要謹(jǐn)慎使用回窘,以避免違反類型安全诺擅。星號投影提供了一種折衷方案,允許我們在不需要具體類型信息時操作集合啡直。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末烁涌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子酒觅,更是在濱河造成了極大的恐慌撮执,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舷丹,死亡現(xiàn)場離奇詭異抒钱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)颜凯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門谋币,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人症概,你說我怎么就攤上這事蕾额。” “怎么了彼城?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵诅蝶,是天一觀的道長。 經(jīng)常有香客問我募壕,道長调炬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任司抱,我火速辦了婚禮筐眷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘习柠。我一直安慰自己匀谣,他們只是感情好照棋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著武翎,像睡著了一般烈炭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宝恶,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天符隙,我揣著相機(jī)與錄音,去河邊找鬼垫毙。 笑死霹疫,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的综芥。 我是一名探鬼主播丽蝎,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼膀藐!你這毒婦竟也來了屠阻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤额各,失蹤者是張志新(化名)和其女友劉穎国觉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虾啦,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡麻诀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缸逃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片针饥。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖需频,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情筷凤,我是刑警寧澤昭殉,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站藐守,受9級特大地震影響挪丢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜卢厂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一乾蓬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧慎恒,春花似錦任内、人聲如沸撵渡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趋距。三九已至,卻和暖如春越除,著一層夾襖步出監(jiān)牢的瞬間节腐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工摘盆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翼雀,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓孩擂,卻偏偏與公主長得像锅纺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子肋殴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容