获取非包扩展属性的KProperty

n9M*_*tq4 4 kotlin

在kotlin中,您可以使用引用运算符来获取包扩展属性的KProperty,如下所示:

val String.extProp: String
    get() = "Some get code"

fun foo() {
    val prop: KProperty<String> = String::extProp
}
Run Code Online (Sandbox Code Playgroud)

但是,当在类中声明扩展属性时,引用运算符不再起作用:

class Example() {

    val String.extProp: String
        get() = "Some get code"

    fun foo() {
        val prop: KProperty<String> = String::extProp // error
    }

}
Run Code Online (Sandbox Code Playgroud)

所以我想知道的是如何在第二个例子中更改有问题的行,所以KProperty得到了什么?

Jay*_*ard 6

你得到的错误是:

错误:(y,x)Kotlin:'extProp'同时是成员和扩展名.不允许引用此类元素

没有语法机制来生成到一个扩展方法,该方法还需要一种含类的引用.例如,您的扩展可能会使用该类的成员,这需要类似于Kotlin 1.1中的" 绑定引用 "(我不确定是否会涵盖此案例,它目前是一个未解决的问题).所以目前还没有::可用的语法.类似Example::String::extProp的东西不可用,也不是常用的Example::String.extProp语法.但你可以通过反思找到它.

首先,您需要知道您将收到的类型是:

KProperty2<INSTANCE, EXTENDING, PROPTYPE>
Run Code Online (Sandbox Code Playgroud)

而一个类的正常属性是:

KProperty1<INSTANCE, PROPTYPE>
Run Code Online (Sandbox Code Playgroud)

您需要知道,因为对getterwill的任何调用都需要类实例和属性正在扩展的类的实例.所以你不能像对类的属性引用那样调用它.

您可以使用此函数查找在类中声明的扩展属性:

@Suppress("UNCHECKED_CAST")
fun <T: Any, EXTENDING: Any, R: Any> KClass<T>.extProp(extends: KClass<EXTENDING>, name: String, returning: KClass<R>): KProperty2<T, EXTENDING, R> {
    return this.declaredMemberExtensionProperties.first {
        it.name == name &&
                it.parameters.size == 2 &&
                it.parameters[0].kind == KParameter.Kind.INSTANCE && it.parameters[0].type == this.defaultType &&
                it.parameters[1].kind == KParameter.Kind.EXTENSION_RECEIVER && it.parameters[1].type == extends.defaultType &&
                it.returnType == returning.defaultType
    } as KProperty2<T, EXTENDING, R>
}
Run Code Online (Sandbox Code Playgroud)

这对于检查来说有点过分,但确保在以后添加任何其他类型的扩展时它是面向未来的.以下是您更新的代码以使用它:

class Example() {
    val String.extProp: String
        get() = "howdy $this"

    fun foo() {
        val prop = Example::class.extProp(String::class, "extProp", String::class)
        println(prop.get(this, "stringy"))  // "howdy stringy"
    }
}
Run Code Online (Sandbox Code Playgroud)