android extensions A cosa serve Kotlin Backing Field?



kotlin visibility package (3)

Come sviluppatore Java, il concetto di un backing field mi è un po 'estraneo. Dato:

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

A cosa serve questo backing field? I documenti di Kotlin hanno detto: Le classi in Kotlin non possono avere campi. Tuttavia, a volte è necessario disporre di un campo di supporto quando si utilizzano gli accessori personalizzati . Perché? Qual è la differenza con l'utilizzo del nome di proprietà stesso all'interno del setter, ad es.

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

Perché, se non hai la parola chiave field , non sarai in grado di impostare / ottenere il valore in get() o set(value) . Ti consente di accedere al campo di supporto negli accessori personalizzati.

Questo è l'equivalente codice Java del tuo campione:

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

Apparentemente questo non è buono, in quanto l'incastonatore è solo una ricorsione infinita in se stesso, non cambia mai nulla. Ricorda in kotlin ogni volta che scrivi foo.bar = value sarà tradotto in una chiamata setter invece che in un PUTFIELD .

EDIT: Java ha campi mentre Kotlin ha proprietà , che è un concetto di livello piuttosto elevato rispetto ai campi.

Esistono due tipi di proprietà: una con un campo di supporto, una senza.

Una proprietà con un campo di supporto memorizzerà il valore sotto forma di un campo. Questo campo rende possibile la memorizzazione del valore in memoria. Un esempio di tale proprietà è la first e la second proprietà di Pair . Quella proprietà cambierà la rappresentazione in memoria di Pair .

Una proprietà senza un campo di supporto dovrà memorizzare il proprio valore in modi diversi dall'archiviazione diretta in memoria. Deve essere calcolato da altre proprietà o dall'oggetto stesso. Un esempio di tale proprietà è la proprietà di estensione dell'indice di List , che non è supportata da un campo, ma un risultato calcolato in base alla proprietà size . Quindi non cambierà la rappresentazione in memoria di List (che non può fare affatto perché Java è tipizzato staticamente).


Inizialmente, anch'io ho avuto difficoltà a capire questo concetto. Quindi permettimi di spiegartelo con l'aiuto di un esempio.

Considera questa classe di Kotlin

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

Ora, quando guardiamo il codice, possiamo vedere che ha 2 proprietà cioè - size (con accessori predefiniti) e isEmpty (con accessori personalizzati). Ma ha solo 1 campo cioè size . Per capire che ha solo un campo, vediamo l'equivalente Java di questa classe.

Vai su Strumenti -> Kotlin -> Mostra Kotlin ByteCode in Android Studio. Clicca su Decompila.

   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;
   }
}

Chiaramente possiamo vedere che la classe java ha solo funzioni getter e setter per isEmpty , e non c'è nessun campo dichiarato per questo. Allo stesso modo in Kotlin, non esiste un campo di supporto per la proprietà È isEmpty , dal momento che la proprietà non dipende affatto da quel campo. Quindi nessun campo di appoggio.

Ora rimuoviamo il getter personalizzato e il setter della proprietà isEmpty .

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

E l'equivalente Java della classe sopra è

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;
   }
}

Qui vediamo sia la size campi che isEmpty . isEmpty è un campo di supporto perché il getter e il setter per la proprietà isEmpty dipendono da questo.


I campi di supporto sono validi per l'esecuzione della convalida o l'attivazione di eventi sul cambio di stato. Pensa alle volte in cui hai aggiunto il codice a un setter / getter Java. I campi di supporto sarebbero utili in scenari simili. Usi i campi di supporto quando hai bisogno di controllare o avere visibilità sui setter / getter.

Quando assegni il campo con il nome del campo stesso, stai effettivamente invocando il setter (cioè set(value) ). Nell'esempio che hai, this.counter = value in set (value) fino a quando non avremo un overflow del nostro stack. L'uso del field esclude il codice setter (o getter).





kotlin-android-extensions