Kotlin中泛型的协变

kotlin 复制代码
interface Shape

class Circle : Shape

fun main() {
    val shapes1: List<Shape> = listOf<Circle>()
    val shapes2: MutableList<Shape> = mutableListOf<Circle>()
}

如上代码,第一行赋值语句是OK的,第二行赋值语句在编辑器上直接就报错了。为什么会这样,这需要理解协变概念。

只读集合类型是协变的,相反,可变集合不是协变的。

协变不协变有什么用?

协变的话,父类型就可以接收子类型,比如:

kotlin 复制代码
val shapes1: List<Shape> = listOf<Circle>()

如上代码,List是一个协变类型,所以泛型Shape可以接收Circle,这是没问题的,因为List是只读的,那么List中的元素就只可能是Circle类型,不会发生改变。

而非协变的话父类型就不能接收子类型,如下:

kotlin 复制代码
val shapes2: MutableList<Shape> = mutableListOf<Circle>()

如上代码,在编辑器中是直接报错的,因为MutableList不是只读的,它可以增、删除 、改,比如shapes2.add(Retangel()),但我们的集合实际是想只保存Circle的,它会导致异常,示例如下:

kotlin 复制代码
interface Shape

class Circle : Shape
class Rectangle: Shape

fun main() {
    val circles: MutableList<Circle> = mutableListOf()
    val shapes: MutableList<Shape> = circles
    shapes.add(Rectangle())
    val circle: Circle = circles[0] // 其实它是一个Rectangle
}

如上代码,如果非协变类型可以子类给父类,这将导致异常,所以在编辑器中这种赋值时会直接报错。

另外,协变和非协变,是看左边的类型,如下代码:

kotlin 复制代码
val shapes1: List<Shape> = listOf<Circle>()
val shapes2: List<Shape> = mutableListOf<Circle>()

如上代码,左边的类型是List,这是只读类型,所以它是协变的,那么它就能接收子类型的集合,不管这个子类型是List还是MutableList都可以。

如果不是协议的,则不能接收子类型,不管子类型是List还是MutableList都不可以。示例如下:

kotlin 复制代码
val shapes1: MutableList<Shape> = listOf<Circle>()
val shapes2: MutableList<Shape> = mutableListOf<Circle>()

如上代码,左边的类型是MutableList,不是只读的,所以它不是协变的,所以不能接收子类型,不管子类型是List还是MutableList都不可以。

相关推荐
mmsx18 小时前
Android 上的 AI 对话链路:流式响应、SSE 解析与三级降级
android·kotlin
YB137519 小时前
Kotlin 引用操作符::
kotlin
维克兜率天2 天前
【维克】弹性策略:用“乖离率“捕捉超跌反弹
android·开发语言·python·深度学习·kotlin·量化
传奇开心果编程2 天前
【用案例学Material 3 Expressive】第1课:从一封邮件开始,感受安卓设计新语言的表现力
android·学习·ui·kotlin·android jetpack
mmsx2 天前
Android 状态保持:进程被杀、旋屏与后台任务的存活术
android·kotlin
传奇开心果编程2 天前
【Jetpack Compose进阶学与练】第14课:系列收尾复习总结;Compose项目常见坑点汇总;学习路线与后续学习方向
android·学习·ui·kotlin·android jetpack
花开路口3 天前
线程安全完全指南:从 Java 到 Kotlin,一文吃透并发编程
java·kotlin
hai_android3 天前
子 View 被压小时,如何向父容器"告状"?——MEASURED_STATE_TOO_SMALL 向上传递机制
android·kotlin·android jetpack
怪奇云呼军3 天前
从 ElevenLabs 看工具调用:闪电智能 Voice Agent 的企业集成验收设计
android·大数据·运维·服务器·网络·人工智能·kotlin
mmsx3 天前
Android UI 复用体系:泛型基类、骨架与插槽
android·kotlin