I’m running into problems combining subclassing polymorphism and generics (ad-hoc polymorphism) in Kotlin.
Here are my type definitions:
interface State
interface StatefulContainer<out S : State> {
val state: S
}
interface StatefulContainerRepository<C: StatefulContainer<S>, S: State>
// Specialization starts here
sealed interface MyState : State
enum class StateA : MyState { A1, A2 }
enum class StateB : MyState { B1, B2 }
sealed interface MyEntity : StatefulContainer<MyState> {
override val state: MyState
}
data class EntityA(override val state: StateA) : MyEntity
data class EntityB(override val state: StateB) : MyEntity
sealed interface MyContainerRepository<C: StatefulContainer<S>, S: MyState>: StatefulContainerRepository<C, S>
class ARepository: MyContainerRepository<EntityA, StateA>
The type checker returns the following error: Type argument is not within its bounds. Expected: StatefulContainer<StateA>. Found: EntityA
. This is odd, because EntityA
is a StatefulContainer<StateA>
– at least this is what I think it is. However, if I make the following modification:
data class EntityA(override val state: StateA) : MyEntity, StatefulContainer<StateA>
the type checker complains Type parameter S of 'StatefulContainer' has inconsistent values: MyState, StateA
. Why is this the case? How can I correctly type the above class hierarchy?
I am used to the more straightforward parametric polymorphism of languages like Haskell, or pure OO subtyping. The combination here, together with the JVM’s type erasure makes it hard for me to understand what is going on. So, besides the concrete question above, I would also be grateful for some more fundamental insights – which concepts are at work, that – if I manage to understand them – would help me to resolve this and similar situations?