[英]Kotlin generic functions and contravariance
我无法解决一个看似简单的问题。 我有Reply
class,它可以包含不同的响应类型 - Views
:
interface View
data class NiceView(val name: String) : View
class MyReply<T : View>(view: T)
现在,我想编写一个 function 接受命令并根据命令返回适当的视图:
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
关键字搞乱协变和逆变,但无济于事。 有人能在这里指出我正确的方向吗?
我无法重现第一个问题,但可以通过简单地在Reply
class 的泛型参数或handle
function 的返回值中添加in
来解决第二个问题:
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
修饰符表示逆变(类似于 Java 中的“?super T”)。
问题是handle()
说T
是一个通用类型,它是View
的一个子类。 所以T
可以是View
的任何子类,但你试图强制它成为NiceView
。 这意味着像这样的代码将不起作用:
val otherReply: Reply<OtherView> = handle(command)
handle
试图返回NiceView
,但通用参数表示它应该是OtherView
。
如果你想保证你的 function 总是返回Reply<T: View>
,你需要构造一个通用类型T
的实例。 这意味着您必须以某种方式识别View
实现。 我不知道您的代码的 rest 是什么样的,但这是一个接受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> {
并不意味着“接受命令并返回适当的视图”的 function。 它的意思是“一个 function 接受一种类型的视图——和一个命令——并返回那种类型的视图的回复。” handle
的调用者可以选择它想要获得的任何类型的View
,这不是您想要的——也不是您已经实现的,因为用户可能想要NiceView
以外的东西。
鉴于您的既定目标,此代码中handle
function 的适当类型是
fun handle(command: Command): Reply<*>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.