Can anyone help me explain what's going on here?
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>
I read from Kotlin docs that if the type is unknown, you can use star projection(*) and then later use any type. So why doesn't it work for the first case? It says Type Mismatch Error
.
Data<*>
is the common supertype of Data<String>
, Data<Any>
, Data<AnythingYouPutThere>
. But Data<State<*>>
is not a common supertype of Data<State<String>>
etc.; it's Data
with a specific type parameter State<*>
(which is the supertype of State<String>
etc.)
Unfortunately, Kotlin doesn't support general existential types as Scala does, but in those terms Data<State<*>>
is Data<State<T> forSome T>
while you want Data<State<T>> forSome T
.
I set
mutableMapOf<String, Data<State<*>>>()
tomutableMapOf<String, Data<out State<*>>>()
and it worked. I don't know why
Data<out State<*>>
allows any subtype of State<*>
as type parameter of Data
. So it can also be expressed as an existential type: Data<T> forSome T : State<*>
, which isn't quite Data<State<T>> forSome T
, because State<*>
can have subtypes which aren't State<Something>
. For example, if you have class State2 extends State<Int>()
, Data<out State<*>>
allows Data<State2>
, but Data<State<T>> forSome T
wouldn't.
Check out the docs here on projection and declaration variance
It says that out is required to tell the compiler the type of the <>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With