委托属性(Delegated Properties)
Delegated Properties我姑且将其称为委托属性,因为实在不知道怎么翻译好,委托属性是一类特殊的Kotlin属性,先来看看最基本的委托属性。
[plain]view plaincopy
class Dog1 {
var name: String by Owner()
}
class Owner {
private var mDogName: String = ""
operator fun getValue(dog: Dog1, property: KProperty<*>): String {
return mDogName
}
operator fun setValue(dog: Dog1, property: KProperty<*>, s: String) {
mDogName = s
}
}
上面的例子中,我们定义了一个Dog类,其内有一个name属性,该属性使用了by关键字,将name属性委托给了Owner类,如果觉得抽象,可以这样理解,Dog有一个name属性,但是该属性的getter和setter则交给了另外一个类来负责实现,也就是说name属性的命运是由其他类来控制的,并非Dog类自己。
Owner类作为Dog类的name属性的被委托类,需要实现getValue和setValue两个operator方法,Kotlin通过operator方法指定一种运算,这里还涉及运算符重载,不再赘述。需要注意的是不要在getValue方法中使用dog.name,这样会出现上一篇文章中的无限递归调用。
上面就是Kotlin的委托属性,Kotlin官方文档给出了一个不错的概括:
1.对于只读属性(如val属性), 委托必须实现getValue方法,该方法的参数如下:
thisRef — 必须和属性所有者类型相同或者是属性所有者类型的超类,如上面的dog:Dog
property — 必须是KProperty<*>类型或者KProperty<*> 的超类
返回值——getValue方法必须返回和属性类型相同类型的返回值
2.对于可变属性(如var属性),委托必须实现setValue方法,该方法的参数如下:
thisRef — 与getValue相同
property — 与getValue相同
new value — 必须和属性相同类型或者是属性类型的超类
了解了委托属性的概念,Kotlin提供了几种现成的委托形式,先来看看懒加载属性。
[plain]view plaincopy
class Dog2 {
val name: String by lazy {
println("First time call me")
"Bebe"
}
}
懒加载属性使用by lazy后跟lambda表达式的形式,lambda表达式内的代码只会在第一次获取属性值时被执行,之后不再执行,例如
[plain]view plaincopy
val dog2 = Dog2()
println(dog2.name)
println(dog2.name)
输出结果为:
First time call me
Bebe
Bebe
下面看看可观察属性
[plain]view plaincopy
class Dog3 {
var name: String by Delegates.observable("Bebe") {
prop, old, new ->
println("My name changes from $old to $new")
}
}
使用by Delegates.observable定义可观察属性,有两个参数,第一个参数是属性的默认值,第二个参数是一个高阶函数,该函数在属性被赋值后将被调用,我们可以做一些观测。下面是调用代码
[plain]view plaincopy
val dog3 = Dog3()
println(dog3.name)
dog3.name = "BEBE"
println(dog3.name)
输出为
Bebe
My name changes from Bebe to BEBE
BEBE
另外还有一个Delegates.vetoable是在属性被赋值前被调用,这里不再赘述,感兴趣可以试试。
最后的一种委托属性可以帮助我们使用Map对常量属性进行初始化,Kotlin文档中介绍,这种委托主要适用于将JSON的数据组织为Map形式,然后初始化数据。
[plain]view plaincopy
class Dog4(initValues: Map) {
val name by initValues
}
调用时
[plain]view plaincopy
val dog4 = Dog4(mapOf("name" to "Bebe"))
println(dog4.name)
Map的key是属性的名称,value是赋值给属性的值。
转载于CSDN博主大鹏1987《Kotlin笔记(七)——委托属性(Delegated Properties)
》