I am a new Kotlin programmer, and I am having a problem relating to generics
In the following code, I am getting an error with it.get(this)
"Type mismatch.
Required: Nothing. Found: Any.
inline fun <reified T : Any> Any.getPropertiesWithType() =
this::class.memberProperties
.filter { it.returnType.isSubtypeOf(T::class.starProjectedType) }
.map {
it.isAccessible = true
it.get(this) as T
}
This is confusing because memberProperties
returns a Collection<KProperty1<T, *>>
where T is the type of this
, which is Any
in my case. KProperty1.get()
takes one argument of that same type T, so I would expect Any
could be passed without an issue.
One thing I noticed is that it
in the filter and map are both type KProperty<out Any, *>>
but memberProperties
does not have the out variance.
If I replace this::class
with this.javaClass.kotlin
, it works without an error, but that seems like a very bad way to go about this.
If anyone knows a way to fix this, or an entirely different strategy, it would be much appreciated. I am new to Kotlin and still do things in the Java way sometimes.
CodePudding user response:
this::class
is analogous to this.getClass()
in Java, which returns a KClass<out Any>
(Class<? extends Object>
in Java). After all, just because the type of this
is Any
, its runtime type may not be Any
- it could be any subclass of Any
. out Any
captures this idea.
Therefore, the memberProperties
of this::class
will be a collection of KProperty1<out Any, *>
.
In the same way that you cannot add anything to a MutableList<out Any>
using add
, you cannot get
the value of a KProperty1<out Any, *>
- an input parameter's type is marked out
. Another way to think about this is that the property could be on any subclass of Any
, trying to get the property using this
, which is just an Any
, obviously doesn't work.
I would move the unchecked cast to it
:
(it as KProperty1<Any, T>).get(this)
As for why .javaClass
works, it is because javaClass
actually gives you a Class<Any>
, not Class<out Any>
. IMO, this doesn't make much sense, but it is what it is.