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都不可以。

相关推荐
androidwork20 小时前
Kotlin与Android Studio开发环境配置指南
开发语言·kotlin·android studio
stevenzqzq20 小时前
kotlin 01flow-StateFlow 完整教程
android·开发语言·kotlin·flow
androidwork20 小时前
使用Kotlin Flow实现Android应用的响应式编程
android·开发语言·kotlin
stevenzqzq20 小时前
kotlin 数据类
android·开发语言·kotlin
大G哥1 天前
Kotlin Lambda语法错误修复
android·java·开发语言·kotlin
androidwork1 天前
Kotlin Android工程Mock数据方法总结
android·开发语言·kotlin
悠哉清闲2 天前
kotlin一个函数返回多个值
kotlin
每次的天空2 天前
Android学习总结之kotlin协程面试篇
android·学习·kotlin
MyhEhud2 天前
Kotlin zip 函数的作用和使用场景
开发语言·windows·kotlin
androidwork2 天前
Kotlin Coroutine与Retrofit网络层构建指南
开发语言·kotlin·retrofit