genericskotlincovariancecontravarianceinvariance

Kotlin generic class property


I know this may seem a repeated question but I am puzzled as to how invariance, covariance and contravariance works.

I can't understand why I can't compile this snippet:

class Test<X: List<Any>>{
    lateinit var list2:List<Any>
    lateinit var list1:X

    fun putList(){
        list2 = emptyList()
        list1 = emptyList<Any>()
    }
}

I get the type mismatch error Required X found List

However if I define the X generic as 'out' I will get a error indicating that the parameter X is invariant in list1 var.

Can someone help another poor soul lost in Kotlin generics?


Solution

  • The short answer: The var list1 is covariant, you're trying to use it in a contravariant way.

    What you're currently trying to do: Assign an instance of the super type (specified by the upper bound) List<Any> to a variable of its sub type X, which is list1. To simplify the problem, consider the following:

    open class Super
    class Sub : Super()
    val sub: Sub = Super() //Compile Error: Type mismatch: inferred type is Super but Sub was expected
    

    You simply can't assign objects to variables of a sub type of that object. The other way around would be fine though: val sup: Super = Sub()