当前位置: 首页 > article >正文

Kotlin协变与逆变区别

在Kotlin中,协变和逆变是泛型编程中的两个重要概念,它们允许我们在类型系统中更加灵活地处理类型关系。
1.协变:协变允许我们使用比原始类型更具体的类型。在kotlin中,通过在类型参数上加out关键字来表示协变,生产者,例如,如果我们有一个泛型类List,其中T是一个协变类型参数,那么我们可以将List赋值给List,因为String是Any的子类型。

2.逆变:逆变允许我们使用比原始类型更一般的类型。在kotlin中,通过在类型参数上加in关键字来表示逆变,消费者,例如,如果我们有一个泛型函数fun foo(list: List),其中T是一个逆变类型参数,那么我们可以将List传递给foo函数,因为Any是String的超类型。

协变代码举例:

interface Producer<out T> {//协变 out 类似java中的 extend
  fun produce(): T
}
open class Fruit
open class Apple: Fruit()


class FruitProducer:Producer<Fruit> {
    override fun produce(): Fruit {
       return Fruit()
    }
}

class AppleProducer:Producer<Apple> {
    override fun produce(): Apple {
        return Apple()
    }
}

fun <T> processProduce(producer:Producer<T>) {
    val product = producer.produce()
    println(product)
}

fun main(){
    var fruitProducer:Producer<Fruit> = FruitProducer()
    var appleProducer:Producer<Apple> = AppleProducer()
    processProduce(fruitProducer)
    processProduce(appleProducer)
//    appleProducer = fruitProducer  //报错,协变,不允许将Producer<Fruit>赋值给Producer<Apple>
//    fruitProducer = appleProducer //协变,允许将Producer<Apple>赋值给Producer<Fruit>

}

逆变代码举例:

interface Consumer<in T>{ //逆变 in 类似java中的super
    fun consume()
}

class FruitConsumer:Consumer<Fruit>{
    override fun consume() {
        println("consume fruit")
    }
}

class AppleConsumer:Consumer<Apple>{
    override fun consume() {
        println("consume apple")
    }
}

inline fun <T> processConsumer(consumer:Consumer<T>){
    consumer.consume()
}


fun main() {
    var fruitConsumer:Consumer<Fruit> = FruitConsumer()
    var appleConsumer:Consumer<Apple> = AppleConsumer()
    processConsumer(fruitConsumer)
    processConsumer(appleConsumer)
//    fruitConsumer = appleConsumer //报错,逆变,不允许将Consumer<Apple>赋值给Consumer<Fruit>
//    appleConsumer = fruitConsumer  //允许将Consumer<Fruit>赋值给Consumer<Apple>,

}


http://www.kler.cn/a/567378.html

相关文章:

  • yolov12 部署瑞芯微 rk3588、RKNN 部署工程难度小、模型推理速度快
  • 大模型应用案例 | 大模型+金融运维,擎创携手某证券创新运维能力新范式
  • Proser:新增CRC计算辅助功能
  • 从UNIX到Linux:操作系统进化史与开源革命
  • 加油站小程序实战05地图加载
  • 计算机毕业设计SpringBoot+Vue.js社团管理系统(源码+文档+PPT+讲解)
  • 如何在工控机上实现机器视觉检测?
  • YOLOv11-ultralytics-8.3.67部分代码阅读笔记-loss.py
  • Kubernetes (K8S) 高效使用技巧与实践指南
  • MySQL 主从同步配置及操作步骤
  • 20250226-代码笔记05-class CVRP_Decoder
  • (十 四)趣学设计模式 之 策略模式!
  • 蓝桥杯试题:二分查找数组元素
  • Leetcode-最大矩形(单调栈)
  • 苹果与小米破冰合作:iPhone 16e全面支持Find My网络,跨生态互通实现技术性突破
  • springboot、deepseek4j、bge-m3和milvus
  • Airflow和PySPARK实现带多组参数和标签的Amazon Redshift数据仓库批量数据导出程序
  • 【网络】数据链路层(以太网帧格式、MTU、ARP)、NAT、内网穿透
  • vue3 keep-alive 页面切换不触发onActivated和onDeactivated方法周期
  • Channel State Information 信道状态信息