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

相关推荐
A0微声z1 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton1 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream2 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin
RdoZam2 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
Kapaseker2 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin
糖猫猫cc3 天前
Kite:两种方式实现动态表名
java·kotlin·orm·kite
如此风景3 天前
kotlin协程学习小计
android·kotlin
Kapaseker3 天前
你搞得懂这 15 个 Android 架构问题吗
android·kotlin
zh_xuan3 天前
kotlin 高阶函数用法
开发语言·kotlin
colicode3 天前
安卓Android语音验证码接口API示例代码:Kotlin/Java版App验证开发
android·java·前端·前端框架·kotlin·语音识别