Kotlin笔记 Delegated Properties

可以将属性的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("") {
        prop, old, new ->
        println("$old -> $new")
    }
}

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

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

将变量存储在map中

class User(val map: Map) {
    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) {
    var name: String by map
    var age: Int     by map
}

你可能感兴趣的:(Kotlin笔记 Delegated Properties)