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

相关推荐
gjxDaniel1 天前
Kotlin编程语言入门与常见问题
android·开发语言·kotlin
野生技术架构师2 天前
Java 21虚拟线程 vs Kotlin协程:高并发编程模型的终极对决与选型思考
java·开发语言·kotlin
言之。2 天前
Kotlin快速入门
android·开发语言·kotlin
常利兵2 天前
Android Gradle 构建脚本现代化:Kotlin DSL (.kts) 与 Groovy DSL 深度对比与实战指南
android·开发语言·kotlin
baidu_247438612 天前
Android kotlin 定时n秒完成时回调,含暂停和继续
android·kotlin
stevenzqzq2 天前
kotlin和compose中使用by
kotlin·compose
符哥20082 天前
Android 开发中如何使用Coroutines
android·kotlin
sinat_267611913 天前
跟着官网学习协程随笔
学习·kotlin
缺一句感谢和缺一句道歉3 天前
Module was compiled with an incompatible version of Kotlin.
java·kotlin
灯火不休ᝰ3 天前
[安卓] Kotlin中的架构演进:从MVC到MVVM
android·架构·kotlin