繁体   English   中英

Kotlin 泛型函数和逆变

[英]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(""))
}

我可以在这里看到两个问题:

  1. 我在返回类型Reply<T>上遇到了这个奇怪的错误,但这只发生在这个玩具示例中,而不是我的生产代码中:

     Type argument is not within its bounds. Expected: View Found: T
  2. 返回Reply()时出错。 这是杀死我大脑的东西,这是我在生产代码中看到的:

     Type mismatch. Required: T Found: NiceView Type mismatch. Required: Reply<T> Found: Reply<NiceView> Type mismatch. Required: View Found: NiceView

我确实尝试使用inout关键字搞乱协变和逆变,但无济于事。 有人能在这里指出我正确的方向吗?

我无法重现第一个问题,但可以通过简单地在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM