0Pricing
Kotlin Academy · Lekcja

Delegaty observable i vetoable

Reaguj na zmiany właściwości za pomocą observable i warunkowo je odrzucaj przy użyciu vetoable.

Delegaty observable i vetoable to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Powtórzenie dotyczące delegatów właściwości

Delegaty właściwości Kotlin pozwalają oddzielnemu obiektowi obsługiwać metody getValue i setValue. Delegates.observable i Delegates.vetoable to wbudowane delegaty z biblioteki standardowej.

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

Składnia observable

observable przyjmuje wartość początkową i wywołanie zwrotne uruchamiane po każdej zmianie; otrzymuje ono właściwość, starą wartość i nową wartość.

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
}

Wywoływanie aktualizacji interfejsu

Delegaty observable świetnie nadają się do wywoływania odświeżenia interfejsu użytkownika po zmianie właściwości bazowej, bez konieczności pełnej konfiguracji 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"
}

Składnia vetoable

vetoable wywołuje funkcję zwrotną przed przypisaniem. Jeśli funkcja zwrotna zwróci false, nowa wartość zostanie odrzucona, a stara pozostanie zachowana.

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
}

Łączenie walidacji z vetoable

Należy użyć vetoable, aby wymuszać niezmienniki domenowe na poziomie właściwości bez zewnętrznej logiki walidacji.

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
}

Rejestrowanie zmian za pomocą observable

Należy użyć observable do rejestrowania audytowego: każda zmiana stanu będzie automatycznie zapisywana bez modyfikowania logiki biznesowej.

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 w klasie

Oba delegaty działają wewnątrz ciał klas tak jak każda inna właściwość.

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 do ograniczania zakresu

Należy ograniczyć właściwość numeryczną do prawidłowego zakresu za pomocą 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
}

Łączenie delegatów

Logikę observable można łączyć ręcznie, pisząc własny delegat, który wewnętrznie wywołuje observable i dodaje dodatkową logikę na każdym etapie.

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 }

Uwaga dotycząca bezpieczeństwa wątkowego

Żaden z delegatów observable i vetoable nie jest domyślnie bezpieczny wątkowo. W przypadku współbieżnego dostępu należy chronić modyfikacje za pomocą Mutex albo synchronizować je zewnętrznie.

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

Praktyczny wzorzec: walidacja formularza

Należy użyć vetoable dla każdego pola w deklaratywnej walidacji formularza: każde pole samo sprawdza poprawność podczas przypisywania.

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

Szybkie sprawdzenie

Kiedy vetoable wywołuje swoją funkcję zwrotną?

Podsumowanie

observable powiadamia po każdej zmianie, a vetoable działa przed przypisaniem i może odrzucić nową wartość. Oba delegaty świetnie nadają się do rejestrowania, walidacji i reaktywnych wzorców właściwości bez zewnętrznych bibliotek.

Często zadawane pytania

Czy lekcja „Delegaty observable i vetoable” jest bezpłatna?

Tak — pełny tekst „Delegaty observable i vetoable” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Delegaty observable i vetoable”?

Reaguj na zmiany właściwości za pomocą observable i warunkowo je odrzucaj przy użyciu vetoable. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Delegaty observable i vetoable”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. by lazy: szczegółowe omówienie odroczonej inicjalizacji
  2. Delegaty observable i vetoable
  3. Pisanie własnego delegata ReadWriteProperty
  4. Delegaty dla Preferences, właściwości opartych na Map i logowania
← Powrót do Kotlin Academy