I am trying to understand Generics here and am struggling. I have a simple code that looks like
interface A {
}
interface B {
}
class C : A, B {
}
fun <T: A> changeVal() : T {
return C()
}
And I get the following error Type mismatch: inferred type is C but T was expected
. What am I getting wrong?
CodePudding user response:
You've written a function that says "Name me a subclass of A
. I'll return an instance of that subclass." This signature is a lie, since you always return C()
, which is a C
instance, not a T
for all T
subclasses of A
.
Generics establish a "for all" relationship. The caller is always the one who decides what the generic instantiates to, not the callee. In your case, you simply want to return A
.
fun changeVal() : A
The feature you're trying to use is called existential typing, and it's not something that's available in Kotlin. In Haskell (with appropriate compiler extensions), the signature might look something like
data AContainer where
AVal :: forall a. a -> AContainer
changeVal :: AContainer
changeVal = ...
but Kotlin does not have this feature. In fact, this is exactly what subtyping in an OOP language is meant to do: it says "I have an object that has these features, but I don't know anything concrete about it". So you don't need generics to express this pattern.