【问题标题】:Using star projection as a supertype in Kotlin在 Kotlin 中使用星形投影作为超类型
【发布时间】:2019-04-13 05:06:45
【问题描述】:

谁能帮我解释一下这里发生了什么?

private val map1 = mutableMapOf<String, Data<State<*>>>()
private val map2 = mutableMapOf<String, Data<*>>()

init {
    map1.put("1", Data<State<String>>()) //it does not work
    map2.put("2", Data<State<String>>()) //it works
    map2.put("3", Data<State<Int>>()) //it works
}

class Data<T>
class State<T>

我从 Kotlin 文档中读到,如果类型未知,您可以使用星形投影(*),然后再使用任何类型。那么为什么它不适用于第一种情况呢?上面写着Type Mismatch Error

【问题讨论】:

  • 这可能是一个愚蠢的想法,但尝试将状态中的 T 更改为不同的字母
  • 我将 mutableMapOf>>() 设置为 mutableMapOf>>() 并且它起作用了。我不知道为什么。 @尼克莫文
  • 注意:我编辑了我的答案以阐明 Data&lt;out State&lt;*&gt;&gt; 与存在类型的关系。发表评论,以便您查看。

标签: android generics kotlin


【解决方案1】:

Data&lt;*&gt;Data&lt;String&gt;Data&lt;Any&gt;Data&lt;AnythingYouPutThere&gt; 的通用超类型。但是Data&lt;State&lt;*&gt;&gt; 不是 Data&lt;State&lt;String&gt;&gt; 等的常见超类型;它是Data,带有特定类型参数State&lt;*&gt;(这是State&lt;String&gt; 等的超类型)

不幸的是,Kotlin 不像 Scala 那样支持一般存在类型,但在这些术语中 Data&lt;State&lt;*&gt;&gt;Data&lt;State&lt;T&gt; forSome T&gt; 而你想要 Data&lt;State&lt;T&gt;&gt; forSome T

我将 mutableMapOf&lt;String, Data&lt;State&lt;*&gt;&gt;&gt;() 设置为 mutableMapOf&lt;String, Data&lt;out State&lt;*&gt;&gt;&gt;() 并且它起作用了。不知道为什么

Data&lt;out State&lt;*&gt;&gt; 允许State&lt;*&gt; 的任何子类型作为Data 的类型参数。所以它也可以表示为存在类型:Data&lt;T&gt; forSome T : State&lt;*&gt;,这不是相当Data&lt;State&lt;T&gt;&gt; forSome T,因为State&lt;*&gt; 可以有不是State&lt;Something&gt; 的子类型。例如,如果您有class State2 extends State&lt;Int&gt;(),则Data&lt;out State&lt;*&gt;&gt; 允许Data&lt;State2&gt;,但Data&lt;State&lt;T&gt;&gt; forSome T 不允许。

【讨论】:

    【解决方案2】:

    projection and declaration variance 上查看文档

    它说需要 out 告诉编译器

    的类型

    【讨论】:

      【解决方案3】:

      根据文档,说你有一个类

      class Source<X>
      

      你不能这样做

      val source: Source<Any> = Source<String>()
      

      即使 String 继承自 Any。这称为不变性。要支持此功能,您必须使用 Kotlin 的声明站点变体。您只需在类型参数 X 中添加 out 修饰符即可。

      class Source<out X>
      

      要注意的是,您不能在 Source 类的任何方法中使用 X,例如

      class Source<out X> {
          fun modifyX(x: X) {} //not allowed
      }
      

      您只能产生 X,即将方法的返回类型设置为 X

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-18
        • 2019-04-05
        • 1970-01-01
        • 2017-10-18
        • 1970-01-01
        • 1970-01-01
        • 2020-10-28
        • 2011-02-16
        相关资源
        最近更新 更多