我是 Kotlin 的新手,我正在尝试编写一些相当简单的代码,但是我不知道如何使用泛型来使其工作。
我有一个Handler
代表事物处理程序的特征。我无法更改处理程序的代码,因为它来自库.
trait Handler<T> {
fun handle(result: T)
}
下面的所有代码都在我的控制之下 -
User
是一个开放类,它有子类,例如AdminUser
and GuestUser
etc.
有一个特质叫做AdminUserAction
执行一些操作来创建 AdminUsers 列表,然后将该列表传递给处理程序List<AdminUser>
-
trait AdminUserAction {
fun then(handler: Handler<List<AdminUser>>)
}
现在我想通过AdminUserAction
处理程序User
代替AdminUser
。假设处理程序只是记录用户的名称,并且不对管理员特定属性执行任何操作。
fun doIt(action: AdminUserAction, printAllNames: Handler<List<User>>) {
action.then(printAllNames)
}
但是,这段代码给了我一个类型不匹配.
由于 Handler 的类型是List<T>
并且是不可变的,前面的代码应该是完全安全的,但是编译器无法弄清楚。
如果我有权访问处理程序的代码,我可以执行以下操作并且它会起作用 -
trait Handler<in T> {
fun handle(result: T)
}
但是,正如我之前所说,我无法修改 Handler,因为它来自库。还有,看来hacky必须这样做,因为处理程序的类型是完全通用的,并且也应该可用于其他类型的处理程序。
我尝试对 Handler 进行子类化并使用它 -
trait ListHandler<in T>: Handler<List<T>> { }
但是现在我收到一条错误消息“参数 T 被声明为‘in’,但出现在 Handler> 中的‘不变’位置”
我试过 -
trait ListHandler<in T>: Handler<List<in T>> { }
但这给了我更多的错误。
为什么这如此令人困惑?我如何使用泛型来使前面的代码正常工作?
Edit:
我可以通过编写一个转换 a 的通用函数来使其工作Handler<List<User>>
into 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 编译器变得更智能,从而不需要这种类型处理?