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的标准委托