问题描述
我无法解决一个看似简单的问题。我有Reply
类,它可以包含不同的响应类型-Views
:
interface View
data class NiceView(val name: String) : View
class MyReply<T : View>(view: T)
fun <T : View> handle(command: Command): Reply<T> {
return Reply(NiceView(""))
}
我可以在这里看到两个问题:
-
我在返回类型
Reply<T>
上遇到这个奇怪的错误,但这仅在此玩具示例中发生,而不在我的生产代码中发生:Type argument is not within its bounds. Expected: View Found: T
-
返回
Reply()
时出错。这是杀死我的大脑的东西,这就是我在生产代码中看到的东西:Type mismatch. required: T Found: NiceView Type mismatch. required: Reply<T> Found: Reply<NiceView> Type mismatch. required: View Found: NiceView
我确实尝试使用in
和out
关键字弄乱协方差和对数,但无济于事。有人可以在这里指出正确的方向吗?
解决方法
我无法重现第一个问题,但只需将in
modifier添加到Reply
类的泛型参数或handle
函数的返回值中,就可以解决第二个问题:
interface View
data class NiceView(val name: String) : View
class Reply<in T : View>(view: T)
fun <T : View> handle(command: Command): Reply<T> {
return Reply(NiceView(""))
}
// OR
class Reply<T : View>(view: T)
fun <T : View> handle(command: Command): Reply<in T> {
return Reply(NiceView(""))
}
in
修饰符表示 contravariance (类似于Java中的“?super T”)。
问题在于handle()
表示T
是泛型类型,它是View
的子类。因此T
可以是View
的任何子类,但是您试图将其强制为NiceView
。这意味着这样的代码将不起作用:
val otherReply: Reply<OtherView> = handle(command)
handle
试图返回NiceView
,但是通用参数说它应该是OtherView
。
如果要保证函数始终返回Reply<T : View>
,则需要构造泛型类型T
的实例。这意味着您必须以某种方式识别View
实现。我不知道您其余的代码是什么样子,但这是一个示例,其中它接受view
作为参数:
fun <T : View> handle(command: Command,view: T): Reply<T> {
return Reply(view)
}
fun main() {
val otherReply: Reply<OtherView> = handle(command,OtherView(""))
}
或者,如果您不想让调用者指定视图类型,则根本不需要通用参数:
fun handle(command: Command): Reply<View> {
return Reply(NiceView(""))
}
,
fun <T : View> handle(command: Command): Reply<T> {
不是 表示“接受命令并返回适当视图”的函数。它的意思是“一个函数,它接受一种视图类型和一个命令,并返回该视图类型的答复。” handle
的 caller 可以选择想要获取的View
类型,这既不是您想要的类型,也不是您已经实现的类型,因为用户可能想要NiceView
以外的内容。
给定您指定的目标,此代码中handle
函数的适当类型是
fun handle(command: Command): Reply<*>