在kotlin中,您可以使用引用运算符来获取包扩展属性的KProperty,如下所示:
val String.extProp: String
get() = "Some get code"
fun foo() {
val prop: KProperty<String> = String::extProp
}
但是,当在类中声明扩展属性时,引用运算符不再起作用:
class Example() {
val String.extProp: String
get() = "Some get code"
fun foo() {
val prop: KProperty<String> = String::extProp // error
}
}
所以我想知道的是如何在第二个例子中更改有问题的行,以便获得KProperty?
答案 0 :(得分:6)
您收到的错误是:
错误:(y,x)Kotlin:&#39; extProp&#39;同时也是会员和分机。不允许引用此类元素
有无语法机制来生成对扩展方法的引用,该扩展方法也需要包含类。例如,您的扩展程序可能会使用该类的成员,这需要像&#34; bound references&#34;进入Kotlin 1.1(我不确定是否也将涉及此案例,目前是open question)。所以现在,没有::
语法可用。像Example::String::extProp
这样的内容不可用,常用的Example::String.extProp
语法也不行。但你可以通过反思找到它。
首先,您需要知道您将收到的类型:
KProperty2<INSTANCE, EXTENDING, PROPTYPE>
而类的正常属性是:
KProperty1<INSTANCE, PROPTYPE>
您需要知道,因为对getter
的任何调用都需要类实例和属性正在扩展的类的实例。所以你不能像对类的属性引用那样调用它。
您可以使用此函数查找在类中声明的扩展属性:
@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>
}
这对于检查来说有点过分,但确保在以后添加任何其他类型的扩展时它是面向未来的。以下是您更新的代码以使用它:
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"
}
}