Function that accept all class that inherited from generic in kotlin

I’m trying to add Example class into a list of Delegate through addDelegate function. Unfortunately, I got an error :

TypeMismatch: Required Delegate<Item, CoreHolder> found Example

Here’s my code (It’s not full code, it just some piece of code that relevant to my question):

interface Delegate <T, VH: CoreHolder> {
    fun onCreate(parent: ViewGroup): VH

    fun onBind(items: List<T>, holder: VH)
}

class DelegateManager<T, VH: CoreHolder> {
    private val delegates = mutableListOf<Delegate<T, VH>>()

    fun addDelegate(delegate: Delegate<T, VH>) {
        delegates.add(delegate)
    }
}

class GenericDelegateManager<T> {
    private val delegateManager = DelegateManager<T, CoreHolder> = DelegateManager()

    fun addDelegate(delegate: Delegate<T, CoreHolder>) {
        delegateManager.addDelegate(adapterDelegate)
    }
}

class Main {
    val genericDelegateManager = GenericDelegateManager<Item>()
    fun main() {
        genericDelegateManager.addDelegate(Example())
        genericDelegateManager.addDelegate(Example2())
    }
}

class Example: Delegate<Item, Example.ViewHolder> {
    class ViewHolder: CoreHolder {
        //...
    }
}
class Example2: Delegate<Item, Example2.ViewHolder> {
    class ViewHolder: CoreHolder {
        //...
    }
}

Current workarounds :
I’ve found 2 workarounds but I think it’s not the best way for doing it,

  1. Change the addDelegate function’s parameter to Delegate<T, out CoreHolder> and cast it to Delegate<T, CoreHolder> but I got a warning “Unchecked Cast”. So the code become
    @SurpressWarning("UNCHECKED_CAST")
    fun addDelegate(delegate: Delegate<T, out CoreHolder>) {
        delegates.add(delegate as Delegate<T, CoreHolder>)     
    }
  1. Change the Delegate interface type parameter to <T, out VH> and change onBind to fun onBind(items: List<T>, holder: @UnsafeVariance VH) so the code become
    interface Delegate <T, out VH: CoreHolder> {
        fun onBind(items: List<T>, holder: @UnsafeVariance VH)
    }

All those two solutions work, can run and behave as expected. But the code isn’t that fancy.

I need that addDelegate() function accept AdapterDelegate<T, CoreHolder) (all classes that inherit CoreHolder for second type parameter). It was work fine on java by using <? extends CoreHolder> . I’ve read kotlin documentation too and found 2 workarounds to solve it which I’ve written above.

Is there another better way to do this solve this kind of problem? Thanks

This cast is unchecked, so you cannot expect that it works properly for any input (see below).

This is an error, the Delegate interface is invariant.


Considering your incomplete code, your first workaround looks more reasonable for me, but you have to keep in mind that Delegate<Item, Example.ViewHolder> and Delegate<Item, Example2.ViewHolder> are incompatible types, so you cannot invoke:

example.onBind(items, example2.onCreate(parent))