1.延迟属性
(1)概念
属性通过lazy()函数返回Lazy
LazyJVM.kt部分源码:
lazy(initializer: () -> T)方法传入一个lambda表达式返回需要委托的属性初始值,并返回委托对象Lazy
/**
* Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
* and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED].
*
* If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access.
*
* Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on
* the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future.
*/
public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
Lazy.kt部分源码
实现了getValue方法,符合只读属性的委托对象要求。
/**
* An extension to delegate a read-only property of type [T] to an instance of [Lazy].
*
* This extension allows to use instances of Lazy for property delegation:
* `val property: String by lazy { initializer }`
*/
@kotlin.internal.InlineOnly
public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
(2)使用
/**
* 定义一个类
*/
class LazyPropertyClass {
/**
* 定义一个属性委托于Lazy<String>对象
*/
val lazyProperty: String by lazy {
//初始化体,首次访问被委托属性时执行,后续访问都不会再执行
println("执行初始化")
"初始化值"
}
}
/**
* 定义一个变量委托于Lazy<Int>对象
*/
val lazyProperty2: Int by lazy {
//初始化体,首次访问被委托属性时执行,后续访问都不会再执行
println("执行初始化")
0
}
fun main(args: Array<String>) {
val lazyPropertyClass = LazyPropertyClass()
println(lazyPropertyClass.lazyProperty)
println(lazyProperty2)
}
运行结果:
执行初始化
初始化值
执行初始化
0
2.属性监听
(1)概念
属性通过委托Delegates类observable方法或者vetoable方法返回的ReadWritProperty对象,监听属性变化。
(2)定义
/**
* 定义一个类
*/
class ListenerPropertyClass {
/**
* 定义一个属性委托于Delegates.vetoable方法返回的ReadWriteProperty对象
* Delegates.vetoable满足条件才能修改成功
*/
var listenerProperty: Int by Delegates.vetoable(0, { property, oldValue, newValue ->
println("监听到属性变化:property->${property.name} oldValue->$oldValue newValue->$newValue")
newValue > 0//满足条件修改成功
})
}
/**
* 定义一个变量委托于Delegates.observable方法返回的ReadWriteProperty的对象
* Delegates.observable无条件修改成功
*/
var listenerProperty1: String by Delegates.observable("初始化值", { property, oldValue, newValue ->
println("监听到属性变化:property->${property.name} oldValue->$oldValue newValue->$newValue")
})
fun main(args: Array<String>) {
val listenerPropertyClass = ListenerPropertyClass()
println(listenerPropertyClass.listenerProperty)//0
listenerPropertyClass.listenerProperty = -1//此处-1小于0,不满足条件修改不成功
println(listenerPropertyClass.listenerProperty)//0
println(listenerProperty1)//初始化值
listenerProperty1 = "修改值"
println(listenerProperty1)//修改值
}
运行结果:
0
监听到属性变化:property->listenerProperty oldValue->0 newValue->-1
0
初始化值
监听到属性变化:property->listenerProperty1 oldValue->初始化值 newValue->修改值
修改值
3.局部变量委托
(1)概念
局部变量委托就是方法的变量委托其他委托类。
(2)条件
委托类需实现getValue、setValue方法,只是get、set相对于类属性需要的委托类,get、set方法参数值有所不同,如下。
/**
* 定义了一个类
* getValue/setValue的thisRef参数类型为Nothing?类型,因此可以将次类作为局部变量的委托类
* Any?类型的thisRef对应的set、get方法的类也可以作为局部变量的委托类(如使用lazy)
*/
class LocalDelegateClass {
private var localDelegateProperty: String = "初始化值"
/**
* setValue方法的thisRef参数类型为Nothing?类型
*/
operator fun setValue(thisRef: Nothing?, property: KProperty<*>, value: String) {
println("setValue")
this.localDelegateProperty = value
}
/**
* getValue方法的thisRef参数类型为Nothing?类型
*/
operator fun getValue(thisRef: Nothing?, property: KProperty<*>): String {
println("getValue")
return this.localDelegateProperty
}
}
fun main(args: Array<String>) {
//局部变量1,委托于委托类
var localProperty: String by LocalDelegateClass()
println(localProperty)
localProperty = "新值"
println(localProperty)
//局部变量2,lazy延迟初始化
val localLazyProperty : String by lazy {
"延迟初始化变量"
}
println(localLazyProperty)
}
运行结果:
getValue
初始化值
setValue
getValue
新值
延迟初始化变量