Kotlin高级——委托
开始
委托模式是将一个对象的职责委托给其他对象完成,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() {
// statement
}
}
// 委托类与被委托类实现同一接口
class Person(method: Method) : Method by method {
// 委托类中自动生成了接口中的方法,并将调用转发给被委托对象
// 当委托类重写了接口方法时,调用委托类重写的方法
override fun method() {
// statement
}
}
属性委托
在属性后使用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
// Map为只读map
class Person(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
// MutableMap为可变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 ->
// statement
}
}
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> {
// thisRef:委托对象的引用,类型可以是委托对象类型或其父类型
// property:KProperty类型,存储属性的元数据
// 返回值:返回属性对应类型或其子类型
override operator fun getValue(thisRef: Person, property: KProperty<*>): String {
return "$thisRef, 这里委托了 ${property.name} 属性"
}
// value:新值,必须是属性对应类型或其父类型
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) {
// statement
}
}
// 委托提供者
class DelegateProvider {
operator fun provideDelegate(person: Person, property: KProperty<*>) : ReadWriteProperty<Person, String> {
// statement
return Delegate() // 返回一个委托对象
}
}
本文由作者按照 CC BY 4.0 进行授权