android kotlin kotlin-android-extensions

android - ¿Para qué sirve Kotlin Backing Field?



kotlin-android-extensions (3)

Como desarrollador de Java, el concepto de un campo de respaldo es un poco extraño para mí. Dado:

class Sample { var counter = 0 // the initializer value is written directly to the backing field set(value) { if (value >= 0) field = value } }

¿Para qué sirve este campo de respaldo? Los documentos de Kotlin dijeron: Las clases en Kotlin no pueden tener campos. Sin embargo, a veces es necesario tener un campo de respaldo cuando se usan accesores personalizados . ¿Por qué? ¿Cuál es la diferencia con el uso del nombre de las propiedades en sí mismo dentro del setter?

class Sample { var counter = 0 set(value) { if (value >= 0) this.counter = value // or just counter = value? } }


Inicialmente, a mí también me costó entender este concepto. Déjame explicarte con la ayuda de un ejemplo.

Considera esta clase de Kotlin

class DummyClass { var size = 0; var isEmpty get() = size == 0 set(value) { size = size * 2 } }

Ahora, cuando miramos el código, podemos ver que tiene 2 propiedades, es decir, size (con isEmpty predeterminados) e isEmpty (con isEmpty personalizados). Pero solo tiene 1 campo, es decir, size . Para entender que solo tiene 1 campo, veamos el equivalente Java de esta clase.

Vaya a Herramientas -> Kotlin -> Mostrar Kotlin ByteCode en Android Studio. Haz clic en Descompilar.

public final class DummyClass { private int size; public final int getSize() { return this.size; } public final void setSize(int var1) { this.size = var1; } public final boolean isEmpty() { return this.size == 0; } public final void setEmpty(boolean value) { this.size *= 2; } }

Claramente podemos ver que la clase java solo tiene funciones getter y setter para isEmpty , y no hay ningún campo declarado para ello. De manera similar, en Kotlin, no existe un campo de respaldo para la propiedad isEmpty , ya que la propiedad no depende en absoluto de ese campo. Por lo tanto, no hay campo de respaldo.

Ahora eliminemos el getter y setter isEmpty propiedad isEmpty .

class DummyClass { var size = 0; var isEmpty = false }

Y el equivalente de Java de la clase anterior es

public final class DummyClass { private int size; private boolean isEmpty; public final int getSize() { return this.size; } public final void setSize(int var1) { this.size = var1; } public final boolean isEmpty() { return this.isEmpty; } public final void setEmpty(boolean var1) { this.isEmpty = var1; } }

Aquí vemos tanto el size los campos como el isEmpty . isEmpty es un campo de respaldo porque el captador y el definidor de la propiedad isEmpty dependen de él.


Los campos de respaldo son buenos para ejecutar la validación o desencadenar eventos en el cambio de estado. Piense en las veces que ha agregado código a un setter / getter de Java. Los campos de respaldo serían útiles en escenarios similares. Usaría campos de respaldo cuando necesitara controlar o tener visibilidad sobre los setters / getters.

Al asignar el campo con el nombre del campo en sí, en realidad estás invocando al setter (es decir, set(value) ). En el ejemplo que tiene, this.counter = value volvería a aparecer en set (value) hasta que desbordemos nuestra pila. El uso del field omite el código de establecimiento (o getter).


Porque, por ejemplo, si no tiene una palabra clave de field , no podrá establecer / obtener el valor en get() o set(value) . Le permite acceder al campo de respaldo en los accesos personalizados.

Este es el código Java equivalente de su muestra:

class Sample { private int counter = 0; public void setCounter(int value) { if (value >= 0) setCounter(value); } public int getCounter() { return counter; } }

Aparentemente esto no es bueno, ya que el setter es solo una recursión infinita en sí mismo, que nunca cambia nada. Recuerde que en kotlin cada vez que escriba foo.bar = value se traducirá en una llamada de establecimiento en lugar de un PUTFIELD .

EDITAR: Java tiene campos mientras que Kotlin tiene propiedades , que es un concepto de nivel bastante más alto que los campos.

Hay dos tipos de propiedades: una con un campo de respaldo, otra sin.

Una propiedad con un campo de respaldo almacenará el valor en forma de campo. Ese campo hace posible almacenar el valor en la memoria. Un ejemplo de dicha propiedad son las propiedades first y second de Pair . Esa propiedad cambiará la representación en memoria de Pair .

Una propiedad sin un campo de respaldo tendrá que almacenar su valor de otra manera que no sea almacenarlo directamente en la memoria. Debe calcularse a partir de otras propiedades o del objeto mismo. Un ejemplo de dicha propiedad es la propiedad de extensión de indices de List , que no está respaldada por un campo, sino por un resultado calculado basado en la propiedad de size . Por lo tanto, no cambiará la representación en memoria de List (lo que no puede hacer en absoluto porque Java está estáticamente tipado).