通过子类来改变Kotlin中类型参数的变化

这个问题来源于我之前关于Kotlin泛型的问题 。 请在这里查看更多关于这个问题背后动机的信息。

我有一个类不受约束的类型参数

trait Handler<T> { fun handle(result: T) } 

我需要创建一个Handler实例,其中TList<O> ,因此是不可变的。 我的想法是子类Handler和注释它作为一个消费者(即通过使用) –

 trait ListHandler<in T>: Handler<List<T>> { } 

然而,这给了我一个错误,说: “参数T被声明为'在',但发生在'不变'的位置Handler<List<T>

错误是什么意思,有什么办法可以解决它?

这个错误意味着,对于所有的编译器都知道,你的声明可能导致运行时失败。 请记住,在检查ListHandler ,编译器不知道Handler中定义了哪些成员,它只知道Handler已经被成功地进行了类型检查,并且它的签名表明类型参数是不变的。 这是必要的,因为Handler可能稍后被改变并重新编译而不用重新编译ListHandler

 trait Handler<T> { fun handle(result: T) fun get() : T } 

有了这样一个声明,写一个破碎的代码很容易:

 // an ill-behaved ListHandler class HandlerImpl<T> : ListHandler<T> { private var storage: List<T> = listOf() override fun handle(result: List<T>) { storage = result } override fun get(): List<T> = storage } // Code using it, that breaks fun main(args: Array<String>) { val anyHandler = HandlerImpl<Any>() anyHandler.handle(listOf(1, 2, 3)) val problematic: ListHandler<String> = anyHandler // The following line requires an element to be a String, but it is an Int problematic.get()[0].length() } 

结果:

 Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String 

在这里看完整的代码。