【发布时间】:2015-07-11 03:22:15
【问题描述】:
我是 Kotlin 的新手,我正在尝试编写一些相当简单的代码,但是我不知道如何使用泛型来使其工作。
我有一个 Handler 特征,它代表事物的处理程序。 我无法更改 Handler 的代码,因为它来自库。
trait Handler<T> {
fun handle(result: T)
}
下面的所有代码都在我的控制之下-
User 是一个开放类,它有AdminUser 和GuestUser 等子类。
名为AdminUserAction 的特征会创建一个AdminUser 列表,然后将列表传递给List<AdminUser> 的处理程序-
trait AdminUserAction {
fun then(handler: Handler<List<AdminUser>>)
}
现在我想为User 传递一个AdminUserAction 处理程序,而不是AdminUser。假设处理程序只记录用户的姓名,而不对管理员特定的属性做任何事情。
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,因为它来自库。此外,似乎必须这样做hacky,因为 Handler 的类型是完全通用的,并且也应该可用于其他类型的处理程序。
我尝试子类化 Handler 并使用它 -
trait ListHandler<in T>: Handler<List<T>> { }
但是现在我收到一条错误消息,提示 “参数 T 被声明为 'in' 但在 Handler 中出现在 'invariant' 位置>”
我试过了-
trait ListHandler<in T>: Handler<List<in T>> { }
但这给了我更多的错误。
为什么会如此混乱?以及如何使用泛型来使前面的代码工作?
编辑:
我可以通过编写一个将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的主体。它什么都不做!然而,为了满足类型,我必须每次都使用它的繁琐。
有没有更好的方法?技术上是否可以让 Kotlin 编译器更智能,从而不需要这种类型的杂耍?
【问题讨论】:
标签: java generics types type-conversion kotlin