interface Shapeclass Circle : Shapefun main() {val shapes1: List<Shape> = listOf<Circle>()val shapes2: MutableList<Shape> = mutableListOf<Circle>()
}
如上代码,第一行赋值语句是OK的,第二行赋值语句在编辑器上直接就报错了。为什么会这样,这需要理解协变概念。
只读集合类型是协变的,相反,可变集合不是协变的。
协变不协变有什么用?
协变的话,父类型就可以接收子类型,比如:
val shapes1: List<Shape> = listOf<Circle>()
如上代码,List是一个协变类型,所以泛型Shape可以接收Circle,这是没问题的,因为List是只读的,那么List中的元素就只可能是Circle类型,不会发生改变。
而非协变的话父类型就不能接收子类型,如下:
val shapes2: MutableList<Shape> = mutableListOf<Circle>()
如上代码,在编辑器中是直接报错的,因为MutableList不是只读的,它可以增、删除 、改,比如shapes2.add(Retangel())
,但我们的集合实际是想只保存Circle
的,它会导致异常,示例如下:
interface Shapeclass Circle : Shape
class Rectangle: Shapefun main() {val circles: MutableList<Circle> = mutableListOf()val shapes: MutableList<Shape> = circlesshapes.add(Rectangle())val circle: Circle = circles[0] // 其实它是一个Rectangle
}
如上代码,如果非协变类型可以子类给父类,这将导致异常,所以在编辑器中这种赋值时会直接报错。
另外,协变和非协变,是看左边的类型,如下代码:
val shapes1: List<Shape> = listOf<Circle>()
val shapes2: List<Shape> = mutableListOf<Circle>()
如上代码,左边的类型是List
,这是只读类型,所以它是协变的,那么它就能接收子类型的集合,不管这个子类型是List
还是MutableList
都可以。
如果不是协议的,则不能接收子类型,不管子类型是List
还是MutableList
都不可以。示例如下:
val shapes1: MutableList<Shape> = listOf<Circle>()
val shapes2: MutableList<Shape> = mutableListOf<Circle>()
如上代码,左边的类型是MutableList
,不是只读的,所以它不是协变的,所以不能接收子类型,不管子类型是List
还是MutableList
都不可以。