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" } } 
  • Cómo usar un setter personalizado en el cuerpo constructor de la class Kotlin
  • No se puede usar .toChar () después de readLine ()
  • Cómo agregar la dependencia RecyclerView - gradle 3
  • ¿Qué significa la palabra key header / impl en kotlin?
  • Cómo implementar TornadoFX WebEngine Callback en Kotlin
  • testing JOOQ postgres jsonb column for key exists
  • Kotlin sobrecarga la ambigüedad de resolución en la biblioteca estándar
  • Error de reference no resuelto al llamar al método add en Kotlin Set interface
  • RxJava2 observable no procesando en Siguiente cuando hay un cambio
  • ¿Cómo save una reference de function como el valor en un tipo de Mapa e invocarlo con un parámetro más adelante en Kotlin?
  • ¿Cuál es la diferencia si elimino la palabra key 'var' en una class?