Kotlin Reflection运算符实现

时间:2017-06-17 16:32:20

标签: reflection kotlin getter

我正在学习Kotlin,目前正在使用Fedora 25 OpenJDK 8和Kotlin 1.1。

我从Kotlin网站复制了这个例子:https://kotlinlang.org/docs/reference/delegated-properties.html并更改了get运算符。

class Example {
var p: String by Delegate()
}

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        // My implementation
        return property.getter.call(thisRef) as String
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name} in $thisRef.'")
    }
}

阅读Reflection文档,getter期望对象实例而没有其他参数,但我只实现了以下错误。 (错误是缩写,因为它太大了,它在递归中。)

.
.
.
at info.malk.Example.getP(Delegation.kt)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at kotlin.reflect.jvm.internal.FunctionCaller$Method.callMethod(FunctionCaller.kt:98)
at kotlin.reflect.jvm.internal.FunctionCaller$InstanceMethod.call(FunctionCaller.kt:115)
at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:107)
at info.malk.Delegate.getValue(Delegation.kt:32)
at info.malk.Example.getP(Delegation.kt)
.
.
.
Caused by: java.lang.reflect.InvocationTargetException
    ... 1024 more
Caused by: java.lang.StackOverflowError
    ... 1024 more

Process finished with exit code 1

帮助。

1 个答案:

答案 0 :(得分:2)

Translation Rule说:

  

例如,对于属性prop,会生成隐藏属性prop$delegate,并且访问者的代码( getter / setter )只会委托给此附加属性。

所以kotlin 属性会将 getter / setter 分派给delegator。当您获取/设置时,委托处理程序( getValue / setValue )中属性周围的值将导致递归调用。

你的Delegate应该更像这样:

class Delegate<T> {

    private var value: T? = null;
    //           ^--- store the proeprty value internal

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return value ?: throw UninitializedPropertyAccessException();
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        this.value = value;
    }
}