Obtenga KProperty de una propiedad de extensión sin package

En kotlin, puede usar el operador de reference para get la propiedad KProperty de una extensión de package como esta:

val String.extProp: String get() = "Some get code" fun foo() { val prop: KProperty<String> = String::extProp } 

Sin embargo, cuando la propiedad de extensión se declara dentro de una class, el operador de reference ya no funciona:

 class Example() { val String.extProp: String get() = "Some get code" fun foo() { val prop: KProperty<String> = String::extProp // error } } 

Entonces, ¿qué me pregunto es cómo puedo cambiar la línea problemática en el segundo ejemplo, para que se obtenga KProperty?

El error que está obteniendo es:

Error: (y, x) Kotlin: 'extProp' es un miembro y una extensión al mismo time. Las references a tales elementos no están permitidas

No hay un mecanismo de syntax para generar una reference a un método de extensión que también requiera una class contenedora. Su extensión, por ejemplo, podría usar miembros de la class, y esto necesitaría algo así como " references enlazadas " en Kotlin 1.1 (que tampoco estoy seguro cubrirá este caso, actualmente es una pregunta abierta ). Entonces, por ahora, no hay una syntax disponible. Cosas como Example::String::extProp no están disponibles, ni tampoco es la syntax comúnmente probada de Example::String.extProp . Pero puedes encontrarlo por reflexión.

Primero necesita saber el tipo que recibirá es:

 KProperty2<INSTANCE, EXTENDING, PROPTYPE> 

Mientras que una propiedad normal en una class es:

 KProperty1<INSTANCE, PROPTYPE> 

Debe saberlo porque cualquier llamada al getter requerirá la instancia de la class y una instancia de la class que la propiedad extiende. Entonces no puedes llamarlo de la misma manera que lo harías con una reference de propiedad de una class.

Puede usar esta function para encontrar una propiedad de extensión declarada en una 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.declanetworkingMemberExtensionProperties.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> } 

Esto es un poco exagerado para la comprobación, pero garantiza que sea a testing de futuro en caso de que se agreguen otros types de extensiones más adelante. El siguiente es su código actualizado para usarlo:

 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" } } 
  • La mejor forma de usar BuffenetworkingReader en Kotlin
  • Deshabilitar un button
  • Kotlin: ¿funciones de extensión y types de plataforma?
  • Invoque el método Java de Kotlin con parámetro de list
  • Usar la habitación como singleton en kotlin
  • Las properties de delegado de Kotlin implementan la function de operador 'provideDelegate', pero el método nunca se llama
  • Función de extensión global en kotlin
  • Cómo ejecutar algún código cuando Gradle está construyendo las testings
  • Cómo extender desde una InnerClass en kotlin
  • Las annotations externas de Kotlin para JDK no están establecidas
  • Encienda un byte