Possible Feature: Kotlin Access Property Name from Delegate

I’m writing a saving system for my game using kotlin delegated properties.

Here is a small example

import kotlin.reflect.KProperty

object Test {
    val test: Int by no_prop { 10 } // I want this
    val testTwo: Int by prop(::testTwo) { 10 } // I don't want this if possible
}

inline fun <reified T : Any> Test.no_prop(initializer: () -> T) = TestProp<T>()

inline fun <reified T : Any> Test.prop(prop: KProperty<*>, initializer: () -> T): TestProp<T> {
    println("My saving key is ${this.javaClass.simpleName}.${prop.name}")
    return TestProp<T>()
}

class TestProp<T : Any> {
    operator fun getValue(thisRef: Any?, property: KProperty<*>) = 10 as T
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {}
}

My game uses a string key for saved properties. Its always *callerClassName*.*propertyName*

I was wondering if its possible through my delegate extension functions or the TestProp class to access the name of the property is delegating?

Ex:
It would be nice if the no_prop method could the property that called it was named “test”

val test: Int by no_prop { 10 }

The following is a workaround, but I’d like to avoid doing that for every property if possible

val testTwo: Int by prop(::testTwo) { 10 }

Is this possible in kotlin?

That is exactly the reasoning behind the provideDelegate operator. Here’s an example based on yours that should work:

import kotlin.reflect.KProperty

object Test {
    val test: Int by no_prop { 10 } // I want this
    val testTwo: Int by prop(::testTwo) { 10 } // I don't want this if possible
}

inline fun <reified T : Any> Test.no_prop(initializer: () -> T) = TestProp<T>()

inline fun <reified T : Any> Test.prop(prop: KProperty<*>, initializer: () -> T): TestProp<T> {
    return TestProp<T>()
}

class TestProp<T : Any> {
    operator fun getValue(thisRef: Any?, property: KProperty<*>) = 10 as T
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {}
    operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): TestProp<T> {
        println("My saving key is ${this.javaClass.simpleName}.${property.name}")
        return this
    }
}
fun main() {
    println(Test.test)
}

It prints:

My saving key is TestProp.test
My saving key is TestProp.testTwo
10
Which is the desired effect.

3 Likes

That is exactly what I was looking for. Thank you!!!

1 Like