🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## [委托属性](http://www.kotlincn.net/docs/reference/delegated-properties.html#%E5%A7%94%E6%89%98%E5%B1%9E%E6%80%A7) [TOC] 什么是委托属性?**属性委托是指一个类的某个属性值不是在类中直接进行定义,而是将其委托给一个代理类,从而实现对该类的属性统一管理**。 **属性委托,提供了一种属性操作的新形式,而不仅仅局限于自身的setter和getter**。 语法结构 ``` val/var <属性名>: <类型> by <表达式> val/var <property name>: <Type> by <expression> ``` 上述语法格式中,**by关键字后面的表达式是委托类**,由于属性对应的get()和set()方法会被委托给getValue()和setValue()方法,因此**属性的委托不必实现任何接口**。对于val类型的属性,只需提供一个getValue()方法即可,但是对于var类型的属性,则需要提供getValue()和setValue()方法。 举一个生活中的委托实例,在过年时小朋友会把自己的压岁钱交给父母来保管,这就是委托。接下来我们来通过程序将这个委托的例子表达出来,具体代码如下所示。 ## 委托属性实现 假如如下场景,“大头儿子还小,小头爸爸给了大头儿子100的压岁钱,同时让大头儿子把压岁钱委托给小头爸爸管理,小头爸爸就可以时刻知道大头儿子压岁钱的使用情况”。 ![](http://upload-images.jianshu.io/upload_images/7368752-a06251b0b73feb6a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](http://upload-images.jianshu.io/upload_images/7368752-867314d4e13770de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 针对以上代码,针对【bigSon】的属性【压岁钱】,之前是经过自身的setter和getter进行读和取。现在它的读和取交给了【smallFather】的【setValue】和【getValue】。 其他提示 1. 【smallFather】的setValue方法和getValue方法需要用operator关键字修饰。 2. 【smallFather】的setValue方法和getValue方法可以通过idea提示自动完成。我们只需要让属性by另一个对象,就会提示我们生成getValue和setValue。 ![](http://upload-images.jianshu.io/upload_images/7368752-82646d6ff9a6e091.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 方便大家运行代码,我们这里提供示例2 ``` import kotlin.reflect.KProperty fun main(args: Array<String>) { val child = Child() println("1.父母给孩子100元压岁钱") child.money = 100 //父母给孩子100元压岁钱 println("2.孩子买个玩具花了50") child.money -= 50 //孩子买个玩具花了50 println("3.孩子自己还剩下多少钱") println("孩子还有${child.money}") //孩子自己还剩下多少钱 } class Child { var money: Int by Parent() //将压岁钱委托给父母 } class Parent() { var money: Int = 0 operator fun getValue(child: Child, property: KProperty<*>): Int { println("Parent类中的getValue()方法被调用," + "获取当前修改的属性名称:" + "${property.name}") return money } operator fun setValue(child: Child, property: KProperty<*>, value: Int) { println("Parent类中的setValue()方法被调用," + "获取当前修改的属性名称:${property.name}、" + "属性值:${value}") money = value } } ``` 运行结果 ``` 1.父母给孩子100元压岁钱 Parent类中的setValue()方法被调用,获取当前修改的属性名称:money、属性值:100 2.孩子买个玩具花了50 Parent类中的getValue()方法被调用,获取当前修改的属性名称:money Parent类中的setValue()方法被调用,获取当前修改的属性名称:money、属性值:50 3.孩子自己还剩下多少钱 Parent类中的getValue()方法被调用,获取当前修改的属性名称:money 孩子还有50 ``` 在上述代码中,创建了一个父母类Parent,在该类创建了两个方法,分别是setValue()和getValue()方法,其中setValue()方法用于设置压岁钱money的值,getValue()方法用于获取money的值。接着创建了一个孩子类Child,在该类中创建了一个属性money,这个属性用于存放孩子的压岁钱,在Child类中将属性money委托给Parent类。 如果Child类中的属性money在未被委托时,是经过自身的setter()和getter()方法进行设置和获取的,被委托之后这个属性的设置和获取交给了被委托的类Parent中的setValue()和getValue()方法,也就是如果孩子把钱委托给父母,则父母就可以时刻知道孩子的压岁钱的使用情况。 >[info]注意 (1)setValue()方法和getValue()方法前必须使用operator关键字修饰(参考operator是[属性委托操作符](http://www.kotlincn.net/docs/reference/operator-overloading.html#%E5%B1%9E%E6%80%A7%E5%A7%94%E6%89%98%E6%93%8D%E4%BD%9C%E7%AC%A6)),将一个函数标记为[重载一个操作符或者实现一个约定](http://www.kotlincn.net/docs/reference/operator-overloading.html) (2)getValue()方法的返回类型必须与委托属性相同或是其子类。 (3)如果委托属性是只读属性,即val类型,则被委托类需要实现getValue()方法。如果委托属性是可变属性,即var类型,则被委托类需要实现getValue()方法和setValue()方法。