gpt4 book ai didi

kotlin - Kotlin 中类型投影的使用站点与声明站点的区别

转载 作者:行者123 更新时间:2023-12-04 12:57:28 25 4
gpt4 key购买 nike

类型层次结构

open class Fruit()

open class CitrusFruit : Fruit()

class Orange : CitrusFruit()

声明站点差异 Crate用作 Fruit 的生产者或消费者s。
不变类
class Crate<T>(private val elements: MutableList<T>) {
fun add(t: T) = elements.add(t) // Consumer allowed
fun last(): T = elements.last() // Producer allowed
}
协变类 out
class Crate<out T>(private val elements: MutableList<T>) {
fun add(t: T) = elements.add(t) // Consumer not allowed: Error
fun last(): T = elements.last() // Producer allowed
}
逆变类in
class Crate<in T>(private val elements: MutableList<T>) {
fun add(t: T) = elements.add(t) // Consumer allowed
fun last(): T = elements.last() // Producer not allowed: Error
}

使用地点差异
所有这些使用地点预测都是针对不变类 Crate<T>上面定义。
无投影
不允许子类型:只有 Crate<Fruit>可以分配给 Crate<Fruit> .
fun main() {
val invariantCrate: Crate<Fruit> = Crate<Fruit>(mutableListOf(Fruit(), Orange()))

invariantCrate.add(Orange()) // Consumer allowed
invariantCrate.last() // Producer allowed
}
协变投影out
允许子类型: Crate<CitrusFruit>可以分配给 Crate<Fruit>CitrusFruitFruit 的子类型.
fun main() {
val covariantCrate: Crate<out Fruit> = Crate<CitrusFruit>(mutableListOf(Orange()))

covariantCrate.add(Orange()) // Consumer not allowed: Error
covariantCrate.last() // Producer allowed
}
逆变投影in
允许子类型: Crate<CitrusFruit>可以分配给 Crate<Orange>CitrusFruitOrange 的父类(super class)型.
fun main() {
val contravariantCrate: Crate<in Orange> = Crate<CitrusFruit>(mutableListOf(Orange()))

contravariantCrate.add(Orange()) // Consumer allowed
contravariantCrate.last() // Producer allowed: No Error?
}

问题
  • 在给定的示例中,我的理解和类型投影的使用是否正确?
  • 对于逆变:为什么是 last() (生产者)功能不允许在声明站点但在使用站点允许?编译器不应该像声明站点示例中显示的那样显示错误吗?也许我错过了什么?如果生产者只允许在使用现场进行逆变,那么它的用例是什么?

  • 我更喜欢带有示例的详细答案,但任何类型的输入都将不胜感激。

    最佳答案

    让我们从使用站点开始。
    当你写

    val contravariantCrate: Crate<in Orange> = ...
    右侧可能是 Crate<Orange> , Crate<Fruit> , Crate<Any?>等。所以基本规则是任何使用 contravariantCrate如果它有任何这些类型应该工作。
    特别是,对于他们所有人
    contravariantCrate.last()
    是合法的(分别为 OrangeFruitAny? )。所以 Crate<in Orange>是合法的并具有类型 Any? . covariantCrate 类似;技术上允许调用使用者方法,只是不能使用 Orange .问题是一个 Crate<Nothing>Crate<out Fruit> ,而你做不到
    val covariantCrate: Crate<Nothing> = ...
    covariantCrate.add(Orange())
    相反,参数类型是 Fruit 的最大公共(public)子类型, CitrusFruit , Nothing等,即 Nothing .和
    covariantCrate.add(TODO())
    确实是合法的,因为 TODO() 的返回类型是 Nothing (但会发出有关无法访问代码的警告)。
    申报网站 inout有效地说,所有用途都是 in/ out .所以对于逆变 class Crate<in T> ,所有调用 last()返回 Any? .所以你应该用那种类型声明它。

    关于kotlin - Kotlin 中类型投影的使用站点与声明站点的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64835413/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com