In the below, since T
is reified, I want to use it "almost as if it were a normal class" by accessing its companion object.
class Cls {
companion object {
fun method() { }
}
}
inline fun <reified T> func() {
T.method() // error
}
fun main() {
func<Cls>()
}
But fails with
Type parameter 'T' cannot have or inherit a companion object, so it cannot be on the left hand side of dot
So it seems that a significant amount of information is lost. I get the same error with and without reified
. I was hoping a reified
type parameter would a fuller generic implementation than Java's. I have a ton of experience in C++ templates.
I've found some workarounds (that are all pretty disappointing using reflection), but really I'm asking why this can't work.
I'm not sure this is answering all the questions, but it's too big for a comment.
First and as stated in the comments, the way the code is written,
T
is not necessarily aCls
so to allow this you'd need some changes:open the class and let Kotlin know
T
is aCls
However, even though it's inlined, this still wouldn't let you call the companion method because
T
has no companion. Even without generics:Doesn't work because companions are not inherited. Why? It was a conscious decision by the Kotlin designers. As you know Kotlin aims to correct a lot of issues Java had and this was one.
Static methods in Java are bound at compile-time while overriding is based on dynamic binding at runtime. This becomes quite confusing when you mix both and Kotlin tried to avoid this. Here's an example:
If
method
would truly be overridden it would print outFoo's method
, but indeed this printsCls' method
. The reason is that there's no overriding, but there's shadowing happening. On the other hand, if the methods wouldn't be static, then you'd getFoo's method
since it is indeed overridden. This apparently caused confusion amongst developers and Kotlin completely disallowed it.