我是Kotlin的新手,我正在尝试编写一些相当简单的代码,但是我无法弄清楚如何使用泛型来使其工作 .
我有一个 Handler
特征,代表事物的处理程序 . I cannot change the code for a Handler as it comes from a library .
trait Handler<T> {
fun handle(result: T)
}
以下所有代码均由我控制 -
User
是一个开放类,具有 AdminUser
和 GuestUser
等子类 .
名为 AdminUserAction
的特性可以创建一个AdminUsers列表,然后将列表传递给 List<AdminUser>
的处理程序 -
trait AdminUserAction {
fun then(handler: Handler<List<AdminUser>>)
}
现在我想为 User
而不是 AdminUser
传递 AdminUserAction
处理程序 . 让's say the handler simply logs the names of the users, and doesn' t对管理员特定属性执行任何操作 .
fun doIt(action: AdminUserAction, printAllNames: Handler<List<User>>) {
action.then(printAllNames)
}
但是,这段代码给了我一个TypeMismatch .
由于Handler属于 List<T>
类型并且是不可变的,因此前面的代码应该是完全安全的,但是编译器无法弄清楚它 .
如果我可以访问Handler的代码,我可以执行以下操作,它可以工作 -
trait Handler<in T> {
fun handle(result: T)
}
但是,正如我之前所说,我不能修改Handler,因为它来自一个库 . 此外,由于Handler的类型是完全通用的,并且也应该可用于其他类型的处理程序,因此看起来很麻烦 .
我尝试了子类化Handler并使用它 -
trait ListHandler<in T>: Handler<List<T>> { }
但是现在我收到一个错误,说"Parameter T is declared as 'in' but occurs in 'invariant' position in Handler>"
我试过了 -
trait ListHandler<in T>: Handler<List<in T>> { }
但这给了我更多的错误 .
为什么这么混乱?我如何使用泛型来使前面的代码工作?
Edit:
我可以通过编写将 Handler<List<User>>
转换为 Handler<List<AdminUser>>
的通用函数来使其工作 -
fun <T: User> fromGeneric(handler: Handler<User>): Handler<T> {
return object: Handler<T> {
override fun handle(result: List<T>) {
handler.handle(result)
}
}
}
然后 -
fun doIt(action: AdminUserAction, printAllNames: Handler<List<User>>) {
action.then(fromGeneric(printAllNames))
}
但是,这似乎很浪费 . 特别是看转换函数 fromGeneric
的正文 . 它正在做 nothing !然而,我必须经历每次使用它的繁琐,以满足类型 .
有没有更好的办法?在技术上是否可以使Kotlin编译器更智能,以便不需要这种类型的jugglery?
1 回答
有几种解决方案:
将
AdminUserAction
的定义更改为或者将
AdminUserAction
的定义更改为或者像这样投射
printAllNames