I\'m playing with reflection and I came out with this problem. When using bound class reference via the ::class
syntax, I get a covariant KClass type:
The reason for covariance in bound ::class
references is, the actual runtime type of an object the expression is evaluated to might differ from the declared or inferred type of the expression.
Example:
open class Base
class Derived : Base()
fun someBase(): Base = Derived()
val kClass = someBase()::class
The expression someBase()
is typed as Base
, but at runtime it's a Derived
object that it gets evaluated to.
Typing someBase()::class
as invariant KClass<Base>
is simply incorrect, in fact, the actuall result of evaluating this expression is KClass<Derived>
.
To solve this possible inconsistency (that would lead to broken type-safety), all bound class references are covariant: someBase()::class
is KClass<out Base>
, meaning that at runtime someBase()
might be a subtype of Base
, and therefore this might be a class token of a subtype of Base
.
This is, of course, not the case with unbound class references: when you take Base::class
, you know for sure that it's the class token of Base
and not of some of its subtypes, so it's invariant KClass<Base>
.