Kotlin:在接口级别使用泛型作为函数的参数类型

umuewwlo  于 2022-11-25  发布在  Kotlin
关注(0)|答案(1)|浏览(125)

在接口级别上使用泛型作为函数的参数类型是不可能的吗?我读过out和in关键字,但据我所知,它们不适用于这种情况。

interface BaseB
    open class ChildB1: BaseB
    open class ChildB2: BaseB

    abstract class BaseMapper<V: BaseB> {
        open fun test(v: V) {
            return
        }
    }

    class TestMapper1: BaseMapper<ChildB1>() {
        override fun test(v: ChildB1) {
            return
        }
    }

    class TestMapper2: BaseMapper<ChildB2>() {
        override fun test(v: ChildB2) {
            return
        }
    }

    @Test
    fun t() {
        //ERROR
        val mappers: List<BaseMapper<BaseB>> = listOf(TestMapper1(), TestMapper2())
        mappers[0].test(ChildB1())
    }
dwthyt8l

dwthyt8l1#

BaseMapper<ChildB1>在逻辑上不是BaseMapper<BaseB>。它消耗ChildB,所以如果你传递了Base的其他实现,如果编译器允许你这么做,它会导致ClassCastException。除了Nothing之外,你的两个子类没有共同的子类型,所以把这两个类型放在同一个列表中的唯一方法是使它成为List<BaseMapper<in Nothing>>
逻辑上不是BaseMapper<BaseB>的原因示例:

open class ChildB1: BaseB {
    fun sayHello() = println("Hello world")
}

class TestMapper1: BaseMapper<ChildB1>() {
    override fun test(v: ChildB1) {
        v.sayHello() // if v is not a ChildB1, this would be impossible
    }
}

//...

val impossibleCast: BaseMapper<BaseB> = TestMapper1()

// TestMapper1 cannot call sayHello() because it's undefined for ChildB2.
// This is impossible:
impossibleCast.test(ChildB2())

// ...so the compiler prevents you from doing the impossible cast in the first place.

相关问题