获取非包扩展属性的KProperty [英] Get KProperty of a non-package extension property

查看:442
本文介绍了获取非包扩展属性的KProperty的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In kotlin, you can use the reference operator to get the KProperty of a package extension property like this:

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

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

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

However, when the extension property is declared inside a class the reference operator no longer works:

class Example() {

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

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

}

所以我想知道的是,如何在第二个示例中更改有问题的行,从而获得KProperty?

So what I am wondering is how can I change the problematic line in the second example, so the KProperty is gotten?

推荐答案

您收到的错误是:

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

Error:(y, x) Kotlin: 'extProp' is a member and an extension at the same time. References to such elements are not allowed

没有没有语法机制来生成对也需要包含类的扩展方法的引用.例如,您的扩展名可能使用该类的成员,这将需要诸如"绑定引用"出现在Kotlin 1.1中(我不确定也不会涉及这种情况,目前它是

There is no syntax mechanism to generate a reference to an extension method that also requires a containing class. Your extension for example might use members of the class, and this would need something like "bound references" coming in Kotlin 1.1 (which I'm not sure will cover this case either, it is currently an open question). So for now, there is no :: syntax available. Things like Example::String::extProp are not available, neither is the commonly tried Example::String.extProp syntax. But you can find it by reflection.

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

First you need to know the type you will receive is:

KProperty2<INSTANCE, EXTENDING, PROPTYPE>

而类的常规属性是:

KProperty1<INSTANCE, PROPTYPE>

您需要知道,因为对getter的任何调用都需要类实例和该属性扩展的类实例.因此,您不能以与引用类的属性引用相同的方式来调用它.

You need to know that because any call to the getter will require the class instance and an instance of the class the property is extending. So you cannot call it the same way as you would a property reference of a class.

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

You can use this function to find an extension property declared in a class:

@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>
}

这对于检查来说有点过头了,但是可以确保以后可以使用任何其他类型的扩展名,从而保证了以后的工作.以下是您使用它的代码更新:

This is a bit overkill for the checking but ensures that it is future-proof in case any other types of extensions are added later. The following is your code updated to use it:

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"
    }
}

这篇关于获取非包扩展属性的KProperty的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆