有人可以帮我解释一下这里发生了什么吗?
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(*),然后再使用任何类型。那么为什么它不适用于第一种情况?它说类型不匹配错误。
答案 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