I want to print values of properties of my class.
fun print() {
val cl = this::class
cl.declaredMemberProperties.filter {it.visibility != KVisibility.PRIVATE}.forEach {
println("${it.name} = ${it.get(this)}")
}
}
When I try to build this code I get compiler error:
Error:(34, 40) Kotlin: Out-projected type 'KProperty1<out SomeClass, Any?>' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1'
When I change this
to class name SomeClass
everything is fine
fun print() {
val cl = SomeClass::class
cl.declaredMemberProperties.filter {it.visibility != KVisibility.PRIVATE}.forEach {
println("${it.name} = ${it.get(this)}")
}
}
So the problem is that compiler changers type of this::class
to KClass<out SomeClass>
instead of using KClass<SomeClass>
. Any idea why does it happen?
The reason for this difference is that, when you use the SomeClass::class
reference, it is sure to be the class token representing SomeClass
and not one of its possible derived classes, therefore it is KClass<SomeClass>
without type projections.
But this::class
written in a function of an open
or abstract
class or an extension function can return a class token of a derived class, therefore, to ensure type safety, the type is out
-projected: KClass<out SomeClass>
means that the actual type argument can be SomeClass
or its subtype.
Example:
open class A {
fun f() {
println(this::class) // KClass<out A> because it can be KClass<B>
}
}
class B : A()
B().f()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With