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)   //报错

        }

运行结果:

 image

三,例子:

代码:

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()
        }

运行结果:

image 

四,例子:

代码:

//生产者 (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()    //男人

        }

运行结果:

image 

posted @ 2025-09-06 08:37  刘宏缔的架构森林  阅读(30)  评论(0)    收藏  举报