vendredi 17 septembre 2021

Access Implementation's property on variable of type Interface

I'm trying to access the delegate of the property (id) of a class (FooImpl). The problem is, this class implements an interface (Foo), and the property in question overrides a property of this interface. The delegate only exists in the class (not that it could exist in the interface).

The problem is that using the :: operator on a variable of type Foo always returns the property of Foo, not that of the actual instance. The problem in code:

import kotlin.reflect.KProperty
import kotlin.reflect.KProperty0
import kotlin.reflect.jvm.isAccessible

interface Foo {
    val id: Int
}

class FooImpl(
    id: Int,
) : Foo {
    override val id: Int by lazy { id }
}

val <T> KProperty<T>.hasDelegate: Boolean
    get() = apply { isAccessible = true }.let { (it as KProperty0<T>).getDelegate() != null }

fun main() {
    val foo: Foo = FooImpl(1)
    println("foo::id.hasDelegate = ${foo::id.hasDelegate}")
    println("(foo as FooImpl)::id.hasDelegate = ${(foo as FooImpl)::id.hasDelegate}")
}

This prints:

foo::id.hasDelegate = false
(foo as FooImpl)::id.hasDelegate = true

But this requires compile-time knowledge of the correct implementation. What I'm looking for is accessing the correct propert without having to specify FooImpl there.

The information is present at runtime because the least (!) intrusive workaround I have found so far is adding fun idProp(): KProperty0<*> to Foo and override fun idProp() = ::id to FooImpl and accessing the property using that.

Is there any better way than that?





Aucun commentaire:

Enregistrer un commentaire