0Pricing
Kotlin Academy · Lección

Delegados observable y vetoable

Reaccione a cambios en propiedades con observable y rechácelos condicionalmente con vetoable.

Delegados observable y vetoable es una lección gratuita de Kotlin Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Kotlin Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Kotlin Academy incluye 4 lecciones en total.

Repaso de los delegados de propiedades

Los delegados de propiedades de Kotlin permiten que un objeto independiente gestione getValue y setValue. Delegates.observable y Delegates.vetoable son delegados integrados de la biblioteca estándar.

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

Sintaxis de observable

observable recibe un valor inicial y una devolución de llamada que se invoca después de cada cambio con la propiedad, el valor anterior y el nuevo valor.

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
}

Activar actualizaciones de la interfaz

Los delegados observables son excelentes para activar la actualización de la interfaz cuando cambia una propiedad de respaldo, sin necesidad de configurar todo 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"
}

Sintaxis de vetoable

vetoable invoca una devolución de llamada antes de la asignación. Si la devolución de llamada devuelve false, se rechaza el nuevo valor y se conserva el anterior.

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
}

Combinar la validación con vetoable

Use vetoable para aplicar invariantes del dominio en el nivel de la propiedad, sin lógica de validación externa.

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
}

Registrar cambios con observable

Use observable para registrar auditorías: registre automáticamente cada transición de estado sin modificar la lógica de negocio.

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 en una clase

Ambos delegados funcionan dentro del cuerpo de una clase, igual que cualquier otra propiedad.

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 para limitar un intervalo

Limite una propiedad numérica a un intervalo válido mediante 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
}

Encadenar delegados

Puede combinar manualmente la lógica de observable escribiendo un delegado personalizado que llame internamente a observable y añada lógica adicional en cada paso.

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 sobre la seguridad de los hilos

Ni observable ni vetoable son seguros para subprocesos de forma predeterminada. Para el acceso simultáneo, proteja las mutaciones con un Mutex o sincronícelas externamente.

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

Patrón práctico: validación de formularios

Use vetoable para cada campo como validación declarativa de formularios: cada campo se valida a sí mismo al asignarle un valor.

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

Comprobación rápida

¿Cuándo invoca vetoable su devolución de llamada?

Resumen

observable notifica después de cada cambio; vetoable se ejecuta antes de la asignación y puede rechazar el nuevo valor. Ambos son excelentes para registrar información, validar y crear patrones de propiedades reactivas sin bibliotecas externas.

Preguntas frecuentes

¿La lección «Delegados observable y vetoable» es gratis?

Sí — el texto completo de «Delegados observable y vetoable» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Kotlin Academy, actualiza a CoddyKit PRO. El curso de Kotlin Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Delegados observable y vetoable»?

Reaccione a cambios en propiedades con observable y rechácelos condicionalmente con vetoable. Practicas Kotlin Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Kotlin Academy?

No se requiere experiencia previa. Kotlin Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «Delegados observable y vetoable»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Kotlin Academy?

Sí. Cada lección de Kotlin Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. by lazy: análisis detallado de la inicialización diferida
  2. Delegados observable y vetoable
  3. Escribir un delegado ReadWriteProperty personalizado
  4. Delegados para preferencias, propiedades respaldadas por mapas y registro
← Volver a Kotlin Academy