07-委托属性
9.2.2 委托属性
在软件开发中,属性的getter和setter函数的代码有很多相同或相似的地方,虽然为每个类编写相同的代码是可行的,但这样做会造成大量的代码冗余,而委托属性正是为解决这一问题而提出的。
属性委托是指一个类的某个属性值不是在类中直接定义,而是将其委托给一个代理类,从而实现对该类属性的统一管理。属性委托的语法格式如下。
val/var <属性名>: <类型> by <表达式>
- val/var:属性类型(只读/可变)。
- 属性名:属性名称。
- 类型:属性的数据类型。
- 表达式:委托代理类。
语法中,关键字by之后的表达式就是委托的类,而且属性的get()方法以及set()方法将被委托给这个对象的getValue()和setValue()方法。属性委托不必实现相关接口, 但必须提供getValue()函数,如果是var类型的属性,还需要提供setValue()函数。为了方便理解,下面看一个委托属性的实例。
fun main(args: Array<String>) {
val e = Example()
println(e.p) // 访问该属性,调用getValue()函数
e.p = "jack" // 调用setValue()函数
println(e.p)
}
//定义包含属性委托的类
class Example {
var p: String by Delegate()
}
//委托的类
class Delegate {
operator fun getValue(ref: Any?, property: KProperty<*>): String {
return "$ref, 委托了${property.name}属性"
}
operator fun setValue(ref: Any?, property: KProperty<*>, value: String) {
println("$ref 的${property.name}属性被赋值为$value")
}
}
运行上面的代码,输出结果如下。
com.xzh.Example@433c675d, 委托了p属性
com.xzh.Example@433c675d 的p属性被赋值为jack
com.xzh.Example@433c675d, 委托了p属性
很明显,委托首先会找到Delegate的实例并调用Delegate的getValue()函数获取p对象,然后给p对象重新赋值并调用setValue()函数保存对象。使用委托属性时,应注意以下几点。
- 如果委托属性是只读属性,则被委托类需要实现getValue方法。
- 如果委托属性是可变属性,则被委托类需要实现getValue和setValue方法。
- 对于getValue方法,其返回类型必须与委托属性类型相同或是其子类型。
- getValue和 setValue方法必须用关键字operator标记。