Las properties de delegado de Kotlin implementan la function de operador 'provideDelegate', pero el método nunca se llama

Tengo un tipo de base DbType que está abierto para la extensión de mis models como este:

 interface DbType { fun <T : Any> field() = PropertyMapper<T>() } 

La class PropertyMapper se implementa de esta manera:

 class PropertyMapper<out T : Any> internal constructor() { @Suppress("UNCHECKED_CAST") operator fun getValue(inst: DbType, prop: KProperty<*>): T { return ImplementationDetail.values?.get(prop.name) as T? ?: throw NullPointerException("No such ${prop.name} in type ${inst::class}") } operator fun provideDelegate(inst: DbType, prop: KProperty<*>): ReadOnlyProperty<DbType, T> { TODO() } } 

De acuerdo con esta input en la documentation de kotlin, debería ser capaz de proporcionar mi propia ReadOnlyProperty<R, T> agregando una function de operador provideDelegate en la class a la que se delega la propiedad. Sin embargo, cuando instalo un object implementando / extendiendo DbType , nunca se invoca la function de operador provideDelegate . La parte "getValue" funciona bien, pero quiero interceptar la creación del delegado de propiedad en el momento en que se crea el object. ¿Alguna idea de lo que estoy haciendo incorrectamente? Aquí hay una class de ejemplo:

 class BasicUserInfo : DbType { val username by field<String>() } 

¿Estás seguro de que no se llama? Lo que encontré mal en su código es que cuando implementa el operador provideDelegate y devuelve algún object delegado que no sea su receptor, no necesita que se implemente el operador getValue , ya que no se usará, es el object que declaraciones provideDelegate que se utilizarán para el acceso a la propiedad (ver a continuación).

De lo contrario, tu código es válido. He modificado ligeramente tu ejemplo para que quede más claro lo que sucede:

 class PropertyMapper<out T : Any> internal constructor() { operator fun getValue(inst: DbType, prop: KProperty<*>): T { println("PropertyMapper :: getValue") // note: never printed TODO() } operator fun provideDelegate(inst: DbType, prop: KProperty<*>): ReadOnlyProperty<DbType, T> { println("PropertyMapper :: provideDelegate") return object : ReadOnlyProperty<DbType, T> { override fun getValue(thisRef: DbType, property: KProperty<*>): T { println("anonymous ReadOnlyProperty :: getValue") TODO() } } } } 

El DbType y el BasicUserInfo se modificaron.

Ahora, cuando creo una instancia de BasicUserInfo y obtengo su username (con la expresión BasicUserInfo().username ), obtengo el siguiente resultado:

 PropertyMapper :: provideDelegate anonymous ReadOnlyProperty :: getValue Exception in thread "main" kotlin.NotImplementedError: An operation is not implemented. ... 

Y si solo creo la instancia, es solo la primera línea.

Por favor, vea la demostración ejecutable de este código .

Lo descubrí: parece ser un error en el plugin de kotlin o gradle. Si construyo un proyecto limpio con PropertyMapper solo con un único método de operador llamado getValue , funciona como se espera: llamando a PropertyMapper#getValue al acceder al campo.

Luego, cuando provideDelegate ese método y en su lugar uso el método del operador provideDelegate , falla con NoSuchMethodError (nunca llama al método PropertyMapper#provideDelegate ). Si limpio (borrando manualmente las carpetas de compilation / salida) y vuelvo a comstackr con esa configuration, funciona perfectamente.

  • No se puede acceder a EditText u otros componentes de la interfaz de usuario con Kotlin
  • No se puede iniciar el animador en una vista separada
  • cómo vincular y mostrar el estado del progreso usando el data binding en adroid
  • @Param no funciona en Spring Data JPA
  • Android Studio y Kotlin: sin cargar cambios
  • Mapbox GeoJSON en la position incorrecta
  • Lectura de carácter nulo en carácter Kotlin por carácter de respuesta socket
  • Memoración de la function miembro de la class de datos Kotlin
  • Diferencia entre con y correr en Kotlin
  • OnErrorNotImplementedException utilizando RxJava2 y Retrofit2 Mosby MVI
  • Observer onChanged nunca llamado