Kotlin笔记 Delegated Properties

作者: yangweigbh | 来源:发表于2017-01-19 13:22 被阅读588次

    可以将属性的get set委托给其他类

    class Example {
        var p: String by Delegate()
    }
    

    当读取或者写入p时,DelegategetValuesetValue会被调用

    class Delegate {
        operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
            return "$thisRef, thank you for delegating '${property.name}' to me!"
        }
     
        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
            println("$value has been assigned to '${property.name} in $thisRef.'")
        }
    }
    

    委托属性的要求

    对于val变量,委托需要提供方法getValue,接收两个参数

    • receiver: property属主类型或者其父类。
    • metadata:KProperty或者其父类
    • return type必须是属性类型或其子类

    var变量,委托需要提供setValue方法,

    • receiver:同上
    • metadata:同上
    • new value: property类型或者父类

    getValuesetValue都需要用operator修饰

    Lazy delegate

    lazy属性接收一个lambda表达式,在第一次get的时候执行lambda表达式,存储并返回lambda表示的结果

    val lazyValue: String by lazy {
        println("computed!")
        "Hello"
    }
    

    lazy表达式的执行是同步的,如果想取消同步,在lazy的构造函数里传入LazyThreadSafetyMode.PUBLICATION

    Observable delegate

    Delegates.observable()接收两个参数,第一个是初始化的值,第二个是变量修改后调用的lambda函数,lambda函数接收三个参数,property, old value, new value。

    
    import kotlin.properties.Delegates
    
    class User {
        var name: String by Delegates.observable("<no name>") {
            prop, old, new ->
            println("$old -> $new")
        }
    }
    
    fun main(args: Array<String>) {
        val user = User()
        user.name = "first"
        user.name = "second"
    }
    

    如果想拦截变量的修改,使用Delegates.vetoable()。vetoable接收两个参数,第一个是初始值,第二个是变量改变前调用的lambda函数,如果lambda返回false,则变量不会被修改

    将变量存储在map中

    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
    ))
    
    println(user.name) // Prints "John Doe"
    println(user.age)  // Prints 25
    

    如果是可变property可以使用MutableMap

    class MutableUser(val map: MutableMap<String, Any?>) {
        var name: String by map
        var age: Int     by map
    }
    

    相关文章

      网友评论

        本文标题:Kotlin笔记 Delegated Properties

        本文链接:https://www.haomeiwen.com/subject/yoribttx.html