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