委托,使用 by 关键字。
委托类
注意点
- 委托者重写方法,则调用会优先委托者内的重写方法
- 委托者重写属性,则被委托者调用不到委托者内的属性
约束
接口,定义通用的业务功能。
被委托者
类,实现约束接口,实现业务功能的具体执行方法。
委托者
类,传入约束,将约束委托给具体的委托者。
具体场景
委托者:用户
被委托者:外卖员
约束:跑腿买东西
/**
* 约束
*/
interface IHelpBuyer {
//送达时间
val time: Int
/**
* 帮忙买东西
* product--商品
*/
fun buyThing(product: String)
/**
* 传递东西
* thing--东西
* receiverName--签收者姓名
*/
fun carryThing(thing: String, receiverName: String)
}
/**
* 被委托对象
* 美团小哥
*/
class MeiTuanXiaoGe(val name: String) : IHelpBuyer {
override val time = 20
override fun buyThing(product: String) {
print("MeiTuan,$name need to buy the $product for the client in $time.")
}
override fun carryThing(thing: String, receiverName: String) {
print("MeiTuan,$name need to carry the $thing for $receiverName in $time.")
}
}
/**
* 被委托对象
* 饿了么小哥
*/
class EleMeXiaoGe(val name: String) : IHelpBuyer {
override val time = 30
override fun buyThing(product: String) {
print("EleMe,$name need to buy the $product for the client in $time.")
}
override fun carryThing(thing: String, receiverName: String) {
print("EleMe,$name need to carry the $thing for $receiverName in $time.")
}
}
/**
* 委托对象
* 用户
*/
class User(val helpBuyer: IHelpBuyer) : IHelpBuyer by helpBuyer {
override val time: Int
get() = 60
/**
* 重写了传递东西的方法
*/
override fun carryThing(thing: String, receiverName: String) {
print("Me need to carry the $thing for $receiverName in $time.")
}
}
/**
* 使用
*/
fun testHelpBuyer() {
//美团小哥Tony
val meiTuanXiaoge1 = MeiTuanXiaoGe("Tony")
//饿了么小哥Alice
val eleMeXiaoGe1 = EleMeXiaoGe("Alice")
//用户1需要买coffee
val buyer1 = User(meiTuanXiaoge1)
buyer1.buyThing("coffee")
//用户2需要买fish
val buyer2 = User(eleMeXiaoGe1)
buyer2.buyThing("fish")
//覆盖由委托实现的接口成员,则会执行委托对象里面的重写方法
val buyer3 = User(meiTuanXiaoge1)
buyer3.carryThing("gift", "Lily")
//在委托者中重写的属性,不会被被委托者使用
print(buyer3.time)
}
委托属性
格式
val/var <属性名>: <类型> by <表达式>
- val 只需要 getValue(),系统提供了 ReadOnlyProperty<in T, out V>
- var 需要 setValue()和 getValue() ,系统提供了 ReadWriteProperty<in T, V>
使用例子
class Example {
var p: String by Delegate()
val m: String by Delegate2()
var n: String by Delegate3()
}
/**
* 属性委托
* var ---需要一个setValue和getValue方法
* val ---只需要getValue方法
*/
class Delegate {
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
}
//val 只读
class Delegate2 : ReadOnlyProperty<Any, String> {
override fun getValue(thisRef: Any, property: KProperty<*>): String {
return "ReadOnlyProperty====,name:${property.name}"
}
}
//var 可读可写
class Delegate3 : ReadWriteProperty<Any, String> {
override fun getValue(thisRef: Any, property: KProperty<*>): String {
return "ReadWriteProperty====,name:${property.name}"
}
override fun setValue(thisRef: Any, property: KProperty<*>, value: String) {
println("ReadWriteProperty====, name:${property.name} value: $value")
}
}
fun testExample() {
val p = Example()
print(p.p)//Example@33a17727, thank you for delegating ‘p’ to me!
p.p = "NEW"//NEW has been assigned to ‘p’ in Example@33a17727.
val m = Example()
print(m.m)//ReadOnlyProperty====,name:m
val n = Example()
print(n.n)//ReadWriteProperty====,name:n
n.n = "NEW"//ReadWriteProperty====, name:n value:NEW
}
标准库中的委托
lazy
延迟属性,只有在第一次调用的时候才会初始化值。
//by lazy
// 第一次调用的时候会初始化,第二调用直接使用值
val myLazy by lazy {
print("This is First.")
"myLazy==="
}
fun testMyLazy() {
println(myLazy)//This is First.myLazy===
println(myLazy)//myLazy===
}
Observable
可观察属性,可以看到值的变化过程。
//Observable 可以观察到数据的变化
var myObservableValue by Delegates.observable("无") { property, oldValue, newValue ->
print("property,$oldValue,$newValue")
}
fun testMyObservableValue() {
myObservableValue = "1111"//property,无,1111
myObservableValue = "2222"//property,1111,2222
}
vetoable
截获赋值并“否决”它们。
//vetoable 通过比较来决定新传入的值是否有效
var myVetoableValue: Int by Delegates.vetoable(1) { _, oldValue, newValue ->
newValue > oldValue
}
fun testMyVetoableValue() {
myVetoableValue = 2//2
myVetoableValue = 5//5
myVetoableValue = 3//5
}
把多个属性储存在一个映射
使用 map 或者 mutableMap 映射存储值
//map 把属性储存在映射中
class Cup(private val map: Map<String, Any?>) {
val color: String by map
val capacity: Int by map
}
fun testCup() {
val cup = Cup(mapOf("color" to "red", "capacity" to 500))
print("$cup.color cup has ${cup.capacity} ml.") //red cup has 500 ml.
}