Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to specify "accepts generic sub-type of a generic type"?

I am trying to implement a function definition that accepts a generic parameter, as long as it extends another specific generic type. In short; param A must extend param B, where A and B are both generic.

My sample example below

abstract class Endpoint<T>(
) {

    private val myList: MutableMap<Class<T>, MutableList<String>> = mutableMapOf()

    fun addToList(
        index: Class<E>, <-- E extends T
        value: String
    ) {
        myList[index] = (myList[index] ?: mutableListOf()).apply { add(value) }
    }

}

Usage example would be

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Some sealed class

sealed class MainSealedClass {
    data class ChildClass(val someParam: Int): MainSealedClass()
}

And the function call

anEndpointInstance.addToList(MainSealedClass.ChildClass::class.java, "some value")

I would like to not having to define E in the abstract class declaration, since T is already defined there.

I tried doing the following as well:

Define myList as accepting keys that extend T as such

val myList: MutableMap<Class<in T>, MutableList<String>>

Define E as a T type (couldn’t find how to specify it extends T in the function

    fun <E:T> addToList(
        index: Class<E>,
        value: String
    ) {
        myList[index] = (myList[index] ?: mutableListOf()).apply { add(value) }
    }
    fun addToList(
        index: Class<in T>,
        value: String
    ) {
        myList[index] = (myList[index] ?: mutableListOf()).apply { add(value) }
    }
    fun <E> addToList(
        index: Class<E>,
        value: String
    ) where E : T {
        myList[index] = (myList[index] ?: mutableListOf()).apply { add(value) }
    }

But it never works. Is there a way of achieving this? I could not find anything in StackOverflow that had an answer for this scenario.

>Solution :

You got your variance inverted. If you want your map to accept Classes of subtypes of T, then it needs to be <out T>. If you’re not inspecting the keys, you could probably just put Class<*>.

Your first way of declaring the function was correct.

abstract class Endpoint<T>(
) {

    private val myList: MutableMap<Class<out T>, MutableList<String>> = mutableMapOf()

    fun <E : T> addToList(
        index: Class<E>,
        value: String
    ) {
        myList.getOrPut(index, ::mutableListOf).add(value)
    }

}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading