Search code examples
javakotlingenericshierarchy

Kotlin - Problem extending a generic class and returning a subtype


I have the following situation:

  • An abstract generic class
abstract class K<T> {
  abstract fun bind(itemModel: T)
}
  • A class that extends from K
class A : K<ModelA> {
    override fun bind(itemModel: ModelA) {
        // ... do anything
    }
}

class B : K<ModelB> {
    override fun bind(itemModel: ModelB) {
        // ... do anything
    }
}
  • Another class, this is a factory that returns a subtype of K based on some parameter:
class Factory {
    companion object {
        const val TYPE_A: Int = 0
        const val TYPE_B: Int = 1

        fun create(type: Int): K {
            return when (type) {
                TYPE_A -> A()
                TYPE_B -> B()
            }
        }
    }
}

At this point, I'm getting an error in return type section of Factory.create method, it says: "One type argument expected for class K< T >". It's clear that I'm trying to return a subtype of K in create method, and it's the only thing that matters, not the specific type of a generic.

This is possible in Java. What is the correct way in Kotlin?


Solution

  • There are multiple things to improve here (updated according to the comment).

    • You need to add default value if the parameter in not TYPE_A or TYPE_B
    • Add * to parametrized K return type.

    As a result it will be something like that:

    fun create(type: Int): K<*> {
       return when (type) {
           TYPE_A -> A()
           TYPE_B -> B()
           else -> throw IllegalStateException("useful message")
        }
    }