开始
委托模式是将一个对象的职责委托给其他对象完成,kotlin 委托通过 by 关键字实现
类委托
将类中的方法委托到被委托对象实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| interface Method { fun method() }
class MethodImpl : Method { override fun method() { } }
class Person(method: Method) : Method by method { override fun method() { } }
|
属性委托
在属性后使用 by 关键字加一个表达式,表达式返回被委托对象,将属性的定义委托给该对象管理
属性的 getter 和 setter 被委托给这个对象的 getValue 和 setValue 方法 (val 属性只需提供 getValue 方法)
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Person { var name: String by Delegate() }
class Delegate : ReadWriteProperty<Person, String> { override operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, 这里委托了 ${property.name} 属性" }
override operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$thisRef 的 ${property.name} 属性赋值为 $value") } }
|
by-lazy 延迟初始化是调用了 lazy 函数,lazy 函数传入一个闭包,返回一个 Lazy 对象,属性定义由 Lazy 对象管理
Lazy 对象只实现了 getValue 方法,因此通常用于 val 属性的延迟初始化
将属性委托到映射
1 2 3 4 5 6 7 8 9 10
| class Person(val map: Map<String, Any?>) { val name: String by map val age: Int by map }
class Student(val map: MutableMap<String, Any?>) { var name: String by map var age: Int by map }
|
可观察属性
kotlin 的 Delegates 类的 observable 方法可以实现属性的观察者,observable 方法传入一个初始值和一个观察者处理器闭包
1 2 3 4 5 6 7 8
| import kotlin.properties.Delegates
class Person { var name: String by Delegates.observable("initValue") { property, oldValue, newValue -> } }
|
Delegates.notNull
用于对一个非空 var 属性进行延迟初始化
lateinit 不支持原始类型,Delegates.notNull 支持所有非空类型
当属性委托给 notNull 后,若未进行初始化直接访问会抛出异常
1 2 3 4 5
| import kotlin.properties.Delegates
class Person { var age: Int by Delegates.notNull<Int>() }
|
自定义委托
创建一个类作为被委托类,对于 val 属性,需要实现 getValue 操作符,对于 var 属性,需要实现 setValue 和 getValue 操作符
- 当属性为 var 时,被委托对象继承 ReadWriteProperty,重写 setValue 和 getValue
- 当属性为 val 时,被委托对象继承 ReadOnlyProperty,重写 getValue
1 2 3 4 5 6 7 8 9 10 11 12
| class Delegate : ReadWriteProperty<Person, String> { override operator fun getValue(thisRef: Person, property: KProperty<*>): String { return "$thisRef, 这里委托了 ${property.name} 属性" } override operator fun setValue(thisRef: Person, property: KProperty<*>, value: String) { println("$thisRef 的 ${property.name} 属性赋值为 $value") } }
|
provideDelegate
用于定义创建被委托对象时的逻辑
通过 provider 委托时,优先调用 provideDelegate,再调用 getValue/setValue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Person { var name: String by DelegateProvider() }
class Delegate : ReadWriteProperty<Person, String> { override operator fun getValue(thisRef: Person, property: KProperty<*>): String { return "" }
override operator fun setValue(thisRef: Person, property: KProperty<*>, value: String) { } }
class DelegateProvider { operator fun provideDelegate(person: Person, property: KProperty<*>) : ReadWriteProperty<Person, String> { return Delegate() } }
|