1

I have the below

open class Model

class WorkOrder : Model()

//An interface

interface ViewInterface<T : Model> {
    fun notifyDataSuccessful(model: T?, models:ArrayList<T>?)
}

class WorkOrderSystemImpl(val viewInterface: ViewInterface<Model>) {

    fun doSomething() {
        val workOrders: ArrayList<WorkOrder> = ArrayList()
        //the below line complains of type mismatch
        viewInterface.notifyDataSuccessful(workOrders)
    }

}

It complains of type-mismatch which is quite strange to me, because WorkOrder is a sub-type of Model and i'd expect it to resolve to same type.

zsmb13
  • 85,752
  • 11
  • 221
  • 226
Paul Okeke
  • 1,384
  • 1
  • 13
  • 19
  • 1
    Check here: https://stackoverflow.com/questions/8481301/covariance-invariance-and-contravariance-explained-in-plain-english/8482091 What you're looking for is called "covariance" – user2340612 Jun 21 '18 at 09:12

1 Answers1

1

It's about the Generics's invariant & covariant, see Kotlin docs here.

In short, you can just remember:

Consumer in, Producer out!

which the Consumer & Producer is determined from the List's view, that means you should think about the role of you List, is it aConsumer or Producer? In your case, the models:ArrayList<T>? is a Producer, because it will be used by the implementation of ViewInterface, so you should define the ViewInterface like this:

interface ViewInterface<T: Model> {
    fun notifyDataSuccessful(model: T?, models: ArrayList<out T>?)
}
Hong Duan
  • 4,234
  • 2
  • 27
  • 50
  • Okay, adding "out" fixed it... and thanks for the Consumer & Producer way of thinking, that should fix my thoughts about kotlin generics as i continue this journey – Paul Okeke Jun 21 '18 at 09:43