2

我正在使用 kotlin 委托属性为我的游戏编写一个保存系统。

这是一个小例子

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) {}
}

我的游戏使用字符串键保存属性。总是如此*callerClassName*.*propertyName*

我想知道是否可以通过我的委托扩展函数或TestProp访问属性名称的类进行委托?

例如:如果 no_prop 方法可以将调用它的属性命名为“test”,那就太好了

val test: Int by no_prop { 10 }

以下是一种解决方法,但如果可能的话,我想避免对每个属性都这样做

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

2 回答 2

2

你可以。每当您创建委托时,您都会实现ReadOnlyProperty(或ReadWriteProperty):

public fun interface ReadOnlyProperty<in T, out V> {
    /**
     * Returns the value of the property for the given object.
     * @param thisRef the object for which the value is requested.
     * @param property the metadata for the property.
     * @return the property value.
     */
    public operator fun getValue(thisRef: T, property: KProperty<*>): V
}

当您尝试访问要委托给(val test: Int by no_prop { 10 }在您的情况下)的属性的值时,该getValue函数将被调用,您将可以访问KProperty. 它有一个name可以用于此目的的字段。

这也适用于类属性和本地属性!

于 2020-10-22T07:00:41.417 回答
0

事实证明,kotlin 有一个“provideDelategate”方法,该方法在创建委托属性时被调用。请参阅https://kotlinlang.org/docs/reference/delegated-properties.html#providing-a-delegate

以下代码有效:

import kotlin.reflect.KProperty

object Test {
    val test: Int by prop { 10 } 
}

inline fun <reified T : Any> Test.prop(prop: KProperty<*>, initializer: () -> T) = 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) {}

    // THIS IS CALLED ON INITIAL CREATION
    operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): TestProp<T> {
        println("My saving key is ${thisRef.javaClass.simpleName}.${property.name}")
        return this
    }
}

fun main() {
    println(Test.test)
}
于 2020-10-22T19:07:49.367 回答