Kotlin: ¿solución alternativa para no lateinit cuando se usa setter personalizado?

En mi actividad tengo un campo que no debe contener nulos y tiene un setter personalizado. Quiero inicializar el campo en mi método onCreate , así que agregué lateinit a mi statement de variables. Pero, al parecer, no puede hacer eso (por el momento): https://discuss.kotlinlang.org/t/lateinit-modifier-is-not-allowed-on-custom-setter/1999 .

Estas son las soluciones alternativas que puedo ver:

  • Hazlo de la manera Java. Haga que el campo sea nulo e inícielo con nulo. No quiero hacer eso.
  • Inicialice el campo con una "instancia pnetworkingeterminada" del tipo. Eso es lo que hago actualmente. Pero eso sería demasiado caro para algunos types.

¿Alguien puede recomendar una mejor manera (que no implique eliminar el setter personalizado)?

Reemplácelo con una propiedad respaldada por una propiedad anulable:

  var _tmp: String? = null var tmp: String get() = _tmp!! set(value) {_tmp=value; println("tmp set to $value")} 

o de esta manera, si quieres que sea consistente con la semántica lateinit :

 var _tmp: String? = null var tmp: String get() = _tmp ?: throw UninitializedPropertyAccessException("\"tmp\" was queried before being initialized") set(value) {_tmp=value; println("tmp set to $value")} 

Esto se puede lograr utilizando una propiedad de respaldo (según la respuesta de Pavlus); sin embargo, prefiero envolverlo dentro de un delegado para evitar exponerlo fuera del context de la propiedad:

 open class LateInit<T: Any> : ReadWriteProperty<Any?, T> { protected lateinit var field: T final override fun getValue(thisRef: Any?, property: KProperty<*>) = get() final override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = set(value) open fun get() = field open fun set(value: T) { field = value } } 

Esto proporciona getters y setters estándar que pueden anularse con una implementación personalizada:

 var upperCaseString by object : LateInit<String>() { override fun set(value: String) { field = value.toUpperCase() } } 

Sin embargo, dado que esta implementación requiere extender el delegado, el tipo genérico no se puede deducir del tipo de propiedad. Esto puede superarse tomando los parameters get y setter personalizados como parameters:

 class LateInit<T: Any>(private val getter: FieldHolder<T>.() -> T = { field }, private val setter: FieldHolder<T>.(T) -> Unit = { field = it }) : ReadWriteProperty<Any?, T> { private val fieldHolder = FieldHolder<T>() override fun getValue(thisRef: Any?, property: KProperty<*>) = fieldHolder.getter() override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = fieldHolder.setter(value) class FieldHolder<T: Any> { lateinit var field: T } } 

Que luego se puede usar así:

 private var upperCaseString: String by LateInit(setter = { field = it.toUpperCase() }) 
  • Cómo usar generics en un object complementario
  • Cómo acceder a la variable de instancia en un object complementario estático en Koltin
  • RxAndroid - Manejar errores con el operador Zip
  • Acceso directo de Kotlin al button en android.support.v4.app.Fragment reference de object nulo
  • Kotlin anonim class implementar interfaz
  • Kotlin Date.daysDespués de la function diferente valor de retorno con los mismos arguments
  • Usar bibliotecas de UI de terceros con TornadoFX
  • Android: la pestaña n. ° 3 borra la vista de list de la pestaña n. ° 1.
  • Kotlin || El elemento Recycleview no está inflando: código inalcanzable en cada método reemplazado de RecycleView.Adapter
  • Sumar un subset de numbers en una list
  • Crea una rueda giratoria que networkingimensiona su ancho cuando se selecciona un elemento