Kotlin泛函数与逆变
我无法解决一个看似简单的问题。我有Kotlin泛函数与逆变,kotlin,generics,contravariance,Kotlin,Generics,Contravariance,我无法解决一个看似简单的问题。我有Reply类,它可以包含不同的响应类型-视图: interface View data class NiceView(val name: String) : View class MyReply<T : View>(view: T) 返回Reply()时出错。这是杀死我大脑的东西,这是我在生产代码中看到的: Type argument is not within its bounds. Expected: View Found: T Type
Reply
类,它可以包含不同的响应类型-视图
:
interface View
data class NiceView(val name: String) : View
class MyReply<T : View>(view: T)
Reply()
时出错。这是杀死我大脑的东西,这是我在生产代码中看到的:
Type argument is not within its bounds.
Expected: View
Found: T
Type mismatch.
Required: T
Found: NiceView
Type mismatch.
Required: Reply<T>
Found: Reply<NiceView>
Type mismatch.
Required: View
Found: NiceView
类型不匹配。
必填项:T
发现:NiceView
类型不匹配。
所需:答复
答复:
类型不匹配。
必需:视图
发现:NiceView
我确实尝试过使用
in
和out
关键字来处理协方差和逆变,但没有效果。有人能给我指出正确的方向吗?我无法重现第一个问题,但第二个问题可以通过简单地添加到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(""))
}
界面视图
数据类视图(val名称:字符串):视图
班级回复(视图:T)
趣味手柄(command:command):回复{
返回回复(视图(“”)
}
//或
班级回复(视图:T)
趣味手柄(command:command):回复{
返回回复(视图(“”)
}
中的修饰符表示逆变(类似于Java中的“.super T”)问题是handle()
表示T
是一个泛型类型,是视图的子类。因此,T
可以是视图
的任何子类,但您试图将其强制为NiceView
。这意味着这样的代码不起作用:
val otherReply: Reply<OtherView> = handle(command)
或者,如果您不关心允许调用方指定视图类型,则根本不需要泛型参数:
fun handle(command: Command): Reply<View> {
return Reply(NiceView(""))
}
fun句柄(command:command):回复{
返回回复(视图(“”)
}
有趣的句柄(command:command):Reply{
并不意味着一个函数“接受一个命令并返回一个适当的视图”。它意味着“一个函数接受一种类型的视图——和一个命令——并返回这种类型的视图。”handle
的调用者可以选择它想要的视图的任何类型,这不是您想要的,也不是您已经实现的,因为用户可能想要的不是NiceView
鉴于您的既定目标,此代码中的句柄
函数的适当类型为
fun handle(command: Command): Reply<*>
fun句柄(command:command):回复
如果你有时间,这是一系列很棒的帖子:太好了!谢谢你的建议!这是我需要atm的地方!:)还有一件事:解释得很好,再次感谢@Louis!这非常有帮助,谢谢!我把我的例子简化了,因为在我的Reply
类中,我还有一个函数,它采用了(T)->String
(一个序列化程序,如果您愿意的话),这不允许我将T指定为逆变:(这是有道理的,谢谢!实际上我会支持你的第二个建议,但由于过于简化,在我的情况下,由于某种原因,它不起作用。我现在实际上返回一个other
。出于某种原因,它会让我指定它为other
fun handle(command: Command): Reply<View> {
return Reply(NiceView(""))
}
fun handle(command: Command): Reply<*>