当前位置:嗨网首页>书籍在线阅读

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标记。