kotlin: 泛型:用out实现协变
一,功能
协变是指在类型参数的继承关系中,允许将一个泛型类型的子类型赋值给父类型。
在 Kotlin 中,我们可以使用 out 关键字来标记类型参数为协变。
这样一来,我们就可以安全地将一个泛型类型的子类型赋值给父类型。
二,例子:
需要注意的地方:虽然协变放宽了对数据类型的约束,可以接受 子类型作为集合中的元素,
但是代价是 无法添加元素,只能获取元素,因此协变只能作为生产者,对外提供数据。
为什么无法添加元素?
因为编译器也不知道会往集合中添加什么类型的数据,
因此索性不允许往集合里添加元素。
代码:
//处理按钮点击事件
binding.button1.setOnClickListener {
//val numbers1: MutableList<Number> = ArrayList<Int>() //报错
//这说明了泛型是不可变的,
// IDE 认为 ArrayList<Integer> 不是 List<Number> 子类型,不允许这么赋值
//解决:使用协变
val numbers2: MutableList<out Number> = ArrayList<Int>(3)
val numbers3: MutableList<out Number> = mutableListOf<Int>(3,5,7)
val f = numbers3.get(0)
println("第一个数字:"+f)
val second:Int = numbers3.get(1).toInt()
println("第二个数字:"+second)
//numbers3.add(100) //报错
//numbers3.add(100) //报错
val numberVal: Number = NumberFormat.getInstance().parse(100.toString())
//numbers3.add(numberVal) //报错
}
运行结果:

三,例子:
代码:
interface Container<out T> {
fun getItem(): T
}
调用
//处理按钮点击事件
binding.button2.setOnClickListener {
open class Animal { //父类
open fun info() {
println("这里是Animal类")
}
}
class Cat : Animal(){ //子类 //父类
override fun info() {
println("这里是Cat类")
}
}
val catContainer: Container<Cat> = object : Container<Cat> {
override fun getItem(): Cat {
return Cat()
}
}
val animalContainer: Container<Animal> = catContainer // 协变
val animal: Animal = animalContainer.getItem() //可以读取数据
println(animal)
println(animal::class.simpleName)
animal.info()
}
运行结果:
四,例子:
代码:
//生产者 (out协变 只能被获取,不能被修改)
interface Product<out T> {
fun getProduct(): T
}
调用:
//处理按钮点击事件:
binding.button3.setOnClickListener {
//父类
open class People() {
open fun show() {
println("people")
}
}
//子类
class Man() : People() {
override fun show() {
println("男人")
}
}
//子类
class Woman() : People() {
override fun show() {
println("女人")
}
}
//使用子类泛型的类
class ProductOne() : Product<Man> {
override fun getProduct(): Man {
return Man()
}
}
//使用子类泛型的类
class ProductTwo() : Product<Woman> {
override fun getProduct(): Woman {
return Woman()
}
}
//out:泛型具体处的子类对象 可以赋值给 泛型声明处的父类对象
var man1: Product<People> = ProductTwo()
val prod1 = man1.getProduct()
prod1.show() //女人
var man2: Product<People> = ProductOne()
val prod2 = man2.getProduct()
prod2.show() //男人
}
运行结果:
浙公网安备 33010602011771号