
5.2.2 委托属性
有一些很常见的属性,虽然我们可以在每次需要它们的时候手动地实现,但更好的方法是一次性全部实现,然后放进一个库里面。换句话说,对其属性值的操作不再依赖于其自身的getter/setter方法,而是将其托付给一个代理类,从而每个使用类中的该属性可以通过代理类统一管理。
委托属性的语法:
val/var <property name>: <Type> by <expression>
其中,by后面的表达式就是一个委托操作。
1.委托属性的第一个例子

执行结果如下:
name: User@65ab7765 value=Tony password: User@65ab7765 value=123456
User对象的两个属性都使用了委托属性的方式。当读取或写入name、password时,Delegate类的getValue()、setValue()会被调用。
委托属性需要使用operator关键字修饰getValue()、setValue()函数。
在Kotlin的官方文档中指出,thisRef必须与属性所有者类型(对于扩展属性指被扩展的类型)相同或者是它的超类型。
2.委托属性的第二个例子
对上述例子做一下改动,新增一个DatabaseDelegate来管理User的属性,DatabaseDelegate用来模拟数据库的操作。

User对象的属性name、password由DatabaseDelegate来管理。

建立一个测试类,当User对象的属性进行读取或者更改时,DatabaseDelegate类的getValue()、setValue()会被调用。

执行结果如下:
loaded value 123456 for field "password" of record 1 tony.password=123456 --------------------------- updating field "password" of record 1 to value P@ssword --------------------------- loaded value P@ssword for field "password" of record 1 tony.password=P@ssword
3.委托属性的第三个例子
将DatabaseDelegate改造成真正操作数据库的类,它的构造函数中包含查询和更新的SQL语句。

此时User对象的属性name、password依然由DatabaseDelegate来管理,但是传入的参数是SQL语句。

在Kotlin的标准库中有一系列的标准委托,如图5-1所示。
· 延迟属性(Lazy Properties):数据只在第一次被访问的时候计算。
· 可观察属性(Observable Properties):监听得到属性的变化通知。
· Map委托属性(Storing Properties in a Map):将所有属性存在Map中。
· 局部委托属性:Kotlin 1.1之后的新特性,可以将局部变量声明为委托属性。
· Not Null:可以返回非空属性。

图5-1 Kotlin的标准委托