0Pricing
Kotlin Academy · Lezione

Delegati observable e vetoable

Reagisca alle modifiche delle proprietà con observable e le rifiuti condizionatamente con vetoable.

Delegati observable e vetoable è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.

Ripasso dei delegati di proprietà

I delegati di proprietà Kotlin consentono a un oggetto separato di gestire getValue e setValue. Delegates.observable e Delegates.vetoable sono delegati integrati della libreria standard.

import kotlin.properties.Delegates
var name: String by Delegates.observable("initial") { prop, old, new ->
    println("${prop.name}: $old -> $new")
}
fun main() { name = "Alice"; name = "Bob" }

Sintassi di observable

observable accetta un valore iniziale e un callback chiamato dopo ogni modifica con la proprietà, il vecchio valore e il nuovo valore.

import kotlin.properties.Delegates
var score: Int by Delegates.observable(0) { _, old, new ->
    println("Score changed from $old to $new")
}
fun main() {
    score = 10
    score = 25
    score = 0
}

Attivare gli aggiornamenti dell'interfaccia

I delegati observable sono ottimi per attivare l'aggiornamento dell'interfaccia quando cambia una proprietà sottostante, senza configurare completamente LiveData.

import kotlin.properties.Delegates
class ViewModel {
    var title: String by Delegates.observable("Loading") { _, _, new ->
        println("Render: $new") // pretend this updates UI
    }
}
fun main() {
    val vm = ViewModel()
    vm.title = "Home"
    vm.title = "Settings"
}

Sintassi di vetoable

vetoable invoca un callback prima dell'assegnazione. Se il callback restituisce false, il nuovo valore viene rifiutato e quello precedente viene mantenuto.

import kotlin.properties.Delegates
var age: Int by Delegates.vetoable(0) { _, old, new ->
    new >= 0 // reject negative ages
}
fun main() {
    age = 25; println(age)  // 25
    age = -1; println(age)  // 25 (rejected)
    age = 30; println(age)  // 30
}

Combinare la convalida con vetoable

Usi vetoable per applicare gli invarianti del dominio a livello di proprietà, senza una logica di convalida esterna.

import kotlin.properties.Delegates
var email: String by Delegates.vetoable("") { _, _, new ->
    new.contains("@")
}
fun main() {
    email = "user@example.com"; println(email) // set
    email = "invalid";          println(email) // still previous
}

Registrare le modifiche con observable

Usi observable per il logging di audit: registri automaticamente ogni transizione di stato senza modificare la logica di business.

import kotlin.properties.Delegates
val log = mutableListOf<String>()
var status: String by Delegates.observable("IDLE") { _, old, new ->
    log.add("$old -> $new")
}
fun main() {
    status = "RUNNING"
    status = "DONE"
    println(log)
}

observable in una classe

Entrambi i delegati funzionano all'interno dei corpi delle classi come qualsiasi altra proprietà.

import kotlin.properties.Delegates
class Counter {
    var count: Int by Delegates.observable(0) { _, old, new ->
        if (new > old) println("Incremented to $new")
        else println("Decremented to $new")
    }
}
fun main() {
    val c = Counter()
    c.count = 5
    c.count = 3
}

vetoable per vincolare un intervallo

Limiti una proprietà numerica a un intervallo valido usando vetoable.

import kotlin.properties.Delegates
var volume: Int by Delegates.vetoable(50) { _, _, new ->
    new in 0..100
}
fun main() {
    volume = 80;  println(volume) // 80
    volume = 150; println(volume) // 80 (rejected)
    volume = 0;   println(volume) // 0
}

Concatenare i delegati

Può combinare manualmente la logica di observable scrivendo un delegato personalizzato che chiama observable internamente e aggiunge logica extra a ogni passaggio.

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class LoggedDelegate<T>(initial: T) : ReadWriteProperty<Any?, T> {
    private var value: T = initial
    override fun getValue(t: Any?, p: KProperty<*>) = value
    override fun setValue(t: Any?, p: KProperty<*>, v: T) {
        println("Setting ${p.name} = $v"); value = v
    }
}
var x: Int by LoggedDelegate(0)
fun main() { x = 10; x = 20 }

Nota sulla sicurezza dei thread

Né observable né vetoable è thread-safe per impostazione predefinita. Per l'accesso concorrente, protegga le mutazioni con un Mutex o sincronizzi esternamente.

import kotlin.properties.Delegates
// Not thread-safe as-is:
var sharedState: String by Delegates.observable("start") { _, old, new ->
    println("$old -> $new")
}
// In coroutines, wrap access with Mutex if needed

Modello pratico: convalida di un modulo

Usi vetoable per ogni campo per una convalida dichiarativa del modulo: ogni campo si convalida autonomamente al momento dell'assegnazione.

import kotlin.properties.Delegates
data class Form(
    var username: String = "",
    var password: String = ""
) {
    var validUsername: String by Delegates.vetoable("") { _,_,v -> v.length >= 3 }
    var validPassword: String by Delegates.vetoable("") { _,_,v -> v.length >= 8 }
}
fun main() {
    val f = Form()
    f.validUsername = "ab";       println(f.validUsername) // ""
    f.validUsername = "alice";    println(f.validUsername) // "alice"
    f.validPassword = "short";    println(f.validPassword) // ""
    f.validPassword = "secure123";println(f.validPassword) // "secure123"
}

Verifica rapida

Quando invoca il proprio callback vetoable?

Riepilogo

observable invia una notifica dopo ogni modifica; vetoable viene eseguito prima dell'assegnazione e può rifiutare il nuovo valore. Entrambi sono ottimi per il logging, la convalida e i modelli di proprietà reattive senza librerie esterne.

Domande Frequenti

La lezione «Delegati observable e vetoable» è gratuita?

Sì — il testo completo di «Delegati observable e vetoable» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.

Cosa imparerò in «Delegati observable e vetoable»?

Reagisca alle modifiche delle proprietà con observable e le rifiuti condizionatamente con vetoable. Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Kotlin Academy?

Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Delegati observable e vetoable»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?

Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. by lazy: approfondimento sull'inizializzazione differita
  2. Delegati observable e vetoable
  3. Scrivere un delegato ReadWriteProperty personalizzato
  4. Delegati per Preferences, proprietà basate su Map e logging
← Torna a Kotlin Academy