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
新值
延遲初始化變量