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).