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
新值
延迟初始化变量

猜你喜欢

转载自www.cnblogs.com/nicolas2019/p/11003895.html