observable 与 vetoable 委托
使用 observable 响应属性变化,并使用 vetoable 按条件拒绝变化。
observable 与 vetoable 委托 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。
属性委托复习
Kotlin 属性委托允许独立对象处理 getValue 和 setValue。Delegates.observable 和 Delegates.vetoable 是标准库提供的内置委托。
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" }observable 语法
observable 接收一个初始值和一个回调。每次更改后都会调用该回调,并传入属性、旧值和新值。
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
}触发界面更新
当支持属性发生变化时,Observable 委托非常适合触发界面刷新,而不需要完整配置 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"
}vetoable 语法
vetoable 会在赋值之前调用回调。如果回调返回 false,新值就会被拒绝,并保留旧值。
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
}使用 vetoable 组合验证
使用 vetoable 在属性级别强制执行领域不变量,而不需要外部验证逻辑。
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
}使用 observable 记录更改日志
使用 observable 进行审计日志记录:自动记录每次状态转换,而无需修改业务逻辑。
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
这两个委托都可以像其他属性一样在类主体中使用。
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 约束范围
使用 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
}串联委托
您可以手动组合 observable 逻辑:编写一个自定义委托,在内部调用 observable,并在每个步骤中添加额外逻辑。
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 }线程安全说明
observable 和 vetoable 默认都不是线程安全的。对于并发访问,请使用互斥锁保护修改操作,或在外部进行同步。
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实践模式:表单验证
为每个字段使用 vetoable,实现声明式表单验证:每个字段在赋值时自行验证。
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"
}快速检查
vetoable 何时调用其回调?
回顾
observable 会在每次更改后发出通知;vetoable 会在赋值前运行,并可以拒绝新值。两者都非常适合在不依赖外部库的情况下实现日志记录、验证和响应式属性模式。
常见问题解答
「observable 与 vetoable 委托」课时是免费的吗?
是的 — 「observable 与 vetoable 委托」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。
「observable 与 vetoable 委托」这节课中我会学到什么?
使用 observable 响应属性变化,并使用 vetoable 按条件拒绝变化。 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Kotlin Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「observable 与 vetoable 委托」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Kotlin Academy 课中编写并运行代码吗?
能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- by lazy:深入了解延迟初始化
- observable 与 vetoable 委托
- 编写自定义 ReadWriteProperty 委托
- 用于偏好设置、Map 支持属性和日志记录的委托