科特林的星空投影

时间:2019-04-13 05:06:45

标签: android generics kotlin

有人可以帮我解释一下这里发生了什么吗?

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文档中了解到,如果类型未知,则可以使用Star Projection(*),然后再使用任何类型。那么为什么它不适用于第一种情况?它说类型不匹配错误。

3 个答案:

答案 0 :(得分:2)

Data<*>Data<String>Data<Any>Data<AnythingYouPutThere>的常见超类型。但是Data<State<*>>不是Data<State<String>>等的常见超类型;它是Data,带有特定类型参数State<*>(是State<String>的超类型,等等)

不幸的是,Kotlin不像Scala那样支持一般的存在类型,但是在这些术语中,Data<State<*>>Data<State<T> forSome T>,而您想使用Data<State<T>> forSome T

  

我将mutableMapOf<String, Data<State<*>>>()设置为mutableMapOf<String, Data<out State<*>>>()并成功了。我不知道为什么

Data<out State<*>>允许State<*>的任何子类型作为Data的类型参数。因此,它也可以表示为存在类型:Data<T> forSome T : State<*>,它不是相当 Data<State<T>> forSome T,因为State<*>可以具有不是{{ 1}}。例如,如果您有State<Something>,则class State2 extends State<Int>()允许Data<out State<*>>,但Data<State2>不允许。

答案 1 :(得分:1)

projection and declaration variance上查看此处的文档

它表示需要告诉编译器<>

的类型

答案 2 :(得分:0)

根据文档,假设您有一个课程

class Source<X>

您不能这样做

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

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

class Source<out X>

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

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

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