kotlin延遲屬性、屬性監聽、局部變量委托


1.延遲屬性

(1)概念

​ 屬性通過lazy()函數返回Lazy 作為委托對象實現 延遲初始化,返回的Lazy 對象實現了getValue符合只讀委托屬性的方法,因此可作為只讀屬性的委托對象。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM