Kotlin基础 — 委托

目录

  1. 类委托
  2. 属性委托
    2.1. 方法一:可以按需继承 ReadOnlyProperty、ReadWriteProperty 两个接口中的一个;
    2.2. 方法二:自己定义,但方法参数必须和 1 中接口的方法参数一致;
  3. 标准委托
    3.1. 延迟属性 Lazy
    3.2. 可观察属性 Observable
    3.3. 把属性储存在映射中
  4. 使用场景

类委托(代理模式)

Delegation pattern

两种类代理的方法

interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}
// 第一种:这里直接使用关键字 by 进行代理
class Derived(base: Base) : Base by base
// 第二种:
class Derived(base: Base) : Base {
    val base : Base
    init {
        this.base = base
    }
    override fun print() {
        base.print() // base是BaseImpl的实例对象
    }
}

// 测试
class Main {
    fun main() {
        val b = BaseImpl(10)
        Derived(b).print() // prints 10
    }
}

属性委托

语法结构: val/var <property name>: <Type> by <expression>

两种实现方法:
  1. 方法一:可以按需继承 ReadOnlyProperty、ReadWriteProperty 两个接口中的一个;

    // 读取属性
    public interface ReadOnlyProperty<in R, out T> {
        public operator fun getValue(thisRef: R, property: KProperty<*>): T
    }
    
    // 读写属性
    public interface ReadWriteProperty<in R, T> {
        // 关键字 operator 重载操作符
        public operator fun getValue(thisRef: R, property: KProperty<*>): T
        public operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
    }

    示例代码:

    class Delegate<T> : ReadWriteProperty<Any?, T> {
        // 重写了getValue()方法
        override fun getValue(thisRef: Any?, property: KProperty<*>): T {
            return ...
        }
    
        override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
    
        }    
    }
    
    class Main {
        var p: String by Delegate<String>()
        fun test() {
            val main = Main()
            print(main.p)  // 会调用到Delegate中的getValue()方法
            main.p = "Elson" // 会调用到Delegate中的setValue()方法
        }
    }
  2. 方法二:自己定义,但方法参数必须和 1 中接口的方法参数一致;

    class Delegate<T> {
        // 使用关键字 operator 来实现重载
        operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
            return "$thisRef, thank you for delegating '${property.name}' to me!"
        }
    
        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
            println("$value has been assigned to '${property.name}' in $thisRef.")
        }
    }

    示例代码:

    class Main {
        var p: String by Delegate<String>() //属性 p 被代理
        fun test() {
            val main = Main()
            print(main.p)  // 会调用到Delegate中的getValue()方法
            main.p = "Elson" // 会调用到Delegate中的setValue()方法
        }
    }

标准委托

1. 延迟属性 Lazy
  1. 示例代码:

    val lazyValue: String by lazy {
        println("computed!")
        "Hello"
    }
    
    fun main(args: Array<String>) {
        println(lazyValue) //第一次调用lazyValue时,会先初始化lazy{}作用区间的代码,即打印一个"computed!",然后返回一个"Hello"字符串并赋值给lazyValue;
        println(lazyValue) //第二次调用lazyValue时,直接将"Hello"赋值给lazyValue;可参考下面的源码
    }
  2. 源码:Lazy.kt 文件

    public fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
    
    private object UNINITIALIZED_VALUE
    
    @JvmVersion
    private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
        private var initializer: (() -> T)? = initializer
        @Volatile private var _value: Any? = UNINITIALIZED_VALUE
        // final field is required to enable safe publication of constructed instance
        private val lock = lock ?: this
    
        override val value: T
            get() {
                val _v1 = _value
                if (_v1 !== UNINITIALIZED_VALUE) {
                    @Suppress("UNCHECKED_CAST")
                    return _v1 as T //第二次执行操作时,这里直接返回对象
                }
    
                return synchronized(lock) {
                    val _v2 = _value
                    if (_v2 !== UNINITIALIZED_VALUE) {
                        @Suppress("UNCHECKED_CAST") (_v2 as T)
                    }
                    else {
                        val typedValue = initializer!!()//第一次使用时执行这里,将lazy大括号内的代码进行初始化,并返回最后一行的数据并赋值给typedValue
                        _value = typedValue 
                        initializer = null
                        typedValue
                    }
                }
            }
    
        override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
    
        override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
    
        private fun writeReplace(): Any = InitializedLazyImpl(value)
    }
    
2. 可观察属性 Observable

示例代码:

class User {
    // 方法一:
    var name: String by Delegates.observable("<no name>") {
        prop, old, new ->
        println("$old -> $new")
    }
    // 方法二:Delegates.observable()实际上就是对ObservableProperty的一层封装
    var name : String by object : ObservableProperty<String>("<no name>") {
        override fun afterChange(property: KProperty<*>, oldValue: String, newValue: String) {
            println("$oldValue -> $newValue")
        }
    }
}

fun main() {
    val user = User()
    user.name = "first"
    user.name = "second"
}

输出结果
< no name > -> first
first -> second

源码:

public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
        ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
            override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
}

public inline fun <T> vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean):
        ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
            // 需要返回一个boolean值,判断是否需要发射,默认为true
            override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue)
}

public abstract class ObservableProperty<T>(initialValue: T) : ReadWriteProperty<Any?, T> {
    private var value = initialValue

    protected open fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true

    protected open fun afterChange (property: KProperty<*>, oldValue: T, newValue: T): Unit {}
    // 代理后,自动被调用
    public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return value
    }
    // 代理后,自动被调用
    public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        val oldValue = this.value
        // 判断是否需要发射,默认为true
        if (!beforeChange(property, oldValue, value)) {
            return
        }
        this.value = value
        afterChange(property, oldValue, value)
    }
}
3. 把属性储存在映射中

这部分不知道怎么看源码

class User(val map: Map<String, Any?>) {
    val name: String by map
    val age: Int     by map
}

val user = User(mapOf(
    "name" to "John Doe",
    "age"  to 25
))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值