标准库中的委托属性:lazy、Delegates.observable
1. 委托属性简介
委托属性(Delegated Properties)是 Kotlin 提供的一种强大特性,允许将属性的 getter 和 setter 逻辑委托给另一个对象处理。Kotlin 标准库内置了多种实用的委托属性实现,如 lazy 和 Delegates.observable,可以简化代码并增强功能。
2. lazy 委托
2.1 基本用法
lazy 用于实现属性的惰性初始化(延迟加载),即属性值在第一次访问时才计算并缓存,后续访问直接返回缓存值。
val expensiveResource: String by lazy {
println("Initializing expensive resource...")
"Loaded Data"
}
fun main() {
println(expensiveResource) // 第一次访问时初始化
println(expensiveResource) // 直接返回缓存值
}
2.2 线程安全模式
lazy 默认是线程安全的(通过 LazyThreadSafetyMode.SYNCHRONIZED),但可以通过参数指定其他模式:
SYNCHRONIZED(默认):线程安全,但性能略低。PUBLICATION:允许多线程初始化,但仅第一个结果被缓存。NONE:非线程安全,适合单线程环境。
val unsafeLazyValue: Int by lazy(LazyThreadSafetyMode.NONE) {
Thread.sleep(1000)
42
}
3. Delegates.observable 委托
3.1 监听属性变化
Delegates.observable 允许在属性值发生变化时触发回调,适用于数据绑定或日志记录等场景。
import kotlin.properties.Delegates
var observedValue: String by Delegates.observable("Initial") {
property, oldValue, newValue ->
println("${property.name} changed from $oldValue to $newValue")
}
fun main() {
observedValue = "New Value" // 输出: observedValue changed from Initial to New Value
}
3.2 结合验证逻辑
可以通过返回布尔值的条件进一步控制赋值是否生效(Delegates.vetoable):
var positiveNumber: Int by Delegates.vetoable(0) { _, old, new ->
new > 0 // 仅允许正数赋值
}
fun main() {
positiveNumber = 10 // 成功
println(positiveNumber) // 10
positiveNumber = -5 // 失败,保持原值
println(positiveNumber) // 10
}
4. 其他标准库委托
4.1 Delegates.notNull
用于非空属性的延迟初始化(类似 lateinit,但支持基本类型):
var notNullValue: Int by Delegates.notNull()
4.2 自定义委托
通过实现 ReadOnlyProperty 或 ReadWriteProperty 接口,可以创建自定义委托:
class CustomDelegate : ReadWriteProperty<Any?, String> {
private var storedValue = "Default"
override fun getValue(thisRef: Any?, property: KProperty<*>): String = storedValue
override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
storedValue = value.toUpperCase()
}
}
var customProperty: String by CustomDelegate()
5. 总结
| 委托类型 | 用途 | 特点 |
|---|---|---|
lazy | 惰性初始化 | 线程安全、缓存结果 |
Delegates.observable | 监听属性变化 | 支持旧值/新值回调 |
Delegates.vetoable | 条件性赋值 | 可拦截无效赋值 |
Delegates.notNull | 延迟初始化的非空属性 | 支持基本类型 |
通过合理使用这些委托属性,可以显著减少样板代码并提升代码的可维护性。
