委派属性
有一些特定类型的属性尽管我们每次可以手动的书写,但是如果有一种很好的方式来实现一次,并且在所有类似的情况下都适用并被加入标准库,这将很有益处。这样的例子可以是下列的情况:
- 懒加载属性:属性会在第一次访问时计算值
- 可观察属性:属性变化时的接口回调通知
- 存储在Map中的属性,而不是为每个属性创建一个字段
为了覆盖这种情况的使用,Kotlin支持委派属性:
class Example {
var p: String by Delegate()
}
定义委派属性的语法形式为:
val/var <property name>: <Type> by <expression>
by之后的表达式就是委派,因为属性的getter和setter方法会被委派给其getValue和setValue方法。属性委派类不需要实现任何接口,但是必须提供getValue方法(对于var属性还需要提供setValue方法)。
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.'")
}
}
在上述的例子中,当我们读取p时将会委派给Delegate的实例,Delegate的getValue方法将会被调用,因此其第一个参数就是包含p属性的那个对象,第二个参数就是p属性的描述(比如属性的名字)。
val e = Example()
println(e.p)
将会打印出:
com.android.mykotlin.Example@3a71f4dd, thank you for delegating 'p' to me!
类似地,当我们给p赋值,setValue方法将会执行。前两个参数与getValue方法一致,第三个参数是待赋的值。
e.p = "NEW"
将会打印出:
NEW has been assigned to 'p in com.android.mykotlin.Example@3a71f4dd.'
成为委派对象的条件请查看下面的内容。
从Kotlin 1.1开始你可以声明委派属性在函数或代码块中,而不是必须要在成员变量中,下面的内容有相关示例。