2

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?

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
Joao Neto
  • 310
  • 3
  • 18

1 Answers1

1

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()

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
  • Yeah. I was under the assumption that List would be a subtype of itself and I could assign subtypes like MutableList and itself... Thanks! – Joao Neto Mar 28 '18 at 18:33