协变逆变

本文解释了编程语言中协变与逆变的概念。协变允许使用比原始指定类型派生程度更高的类型,而逆变则允许使用派生程度更低的类型。

在编程语言中,“协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。 “逆变”则是指能够使用派生程度更小的类型。

在 Kotlin 中,泛型类型具有逆变和不的特性,这些特性有助于处理泛型类型之间的子类型关系。 ### 概念 - ****:Kotlin 使用 `out` 关键字来支持,等同于 Java 中的上界通配符 `? extends`。表示如果 `B` 是 `A` 的子类型,那么 `Producer<B>` 可以被视为 `Producer<A>` 的子类型。类型参数只能用在输出位置(如函数返回值),因为这样可以保证类型安全。例如: ```kotlin class Producer<out T> { fun produce(): T { return null as T } } val producer: Producer<Animal> = Producer<Dog>() // 允许这样的赋值 ``` - **逆变**:Kotlin 使用 `in` 关键字来支持逆变,等同于 Java 中的下界通配符 `? super`。逆变表示如果 `B` 是 `A` 的子类型,那么 `Consumer<A>` 可以被视为 `Consumer<B>` 的子类型。逆变类型参数只能用在输入位置(如函数参数),以确保类型安全。例如: ```kotlin class Consumer<in T> { fun consume(t: T) { println(t) } } val consumer: Consumer<Dog> = Consumer<Animal>() // 逆变允许这样的赋值 ``` - **不**:Kotlin 中的泛型默认是不的,即如果 `B` 是 `A` 的子类型,`GenericClass<B>` 和 `GenericClass<A>` 之间没有子类型关系。例如,`MutableList<Dog>` 不能赋值给 `MutableList<Animal>`,反之亦然。 ### 应用 - **的应用**:常用于只生产数据的类,如集合的只读视图。`List<out T>` 可以安全地从子类类型转换为父类类型,因为它只提供读取操作,不会修改集合内容。例如: ```kotlin val dogList: List<Dog> = listOf(Dog()) val animalList: List<Animal> = dogList // 允许这样的赋值 ``` - **逆变的应用**:逆变常用于只消费数据的类,如比较器。`Comparator<in T>` 可以接受更具体的类型作为参数,因为它只对传入的数据进行操作。例如: ```kotlin val animalComparator: Comparator<Animal> = Comparator { a1, a2 -> a1.id - a2.id } val dogComparator: Comparator<Dog> = animalComparator // 逆变允许这样的赋值 ``` - **不的应用**:当泛型类既生产又消费数据时,通常使用不的泛型类型。例如 `MutableList<T>` 既可以添加元素(消费)又可以获取元素(生产),因此它是不的。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值