Kotlin 委托
委托模式 是一种 通过 对象组合 实现代码重用 的设计模式,
对象处理请求时 将其 委托给 其他对象(委托)处理。
Kotlin 委托 分为:
- 类的委托
- 属性的委托
一、类的委托
委托
Delegate
是实现继承的一种替代方式。达到了 多继承、代码复用 目的。我们知道Java本身不支持多继承的,而是通过 接口 实现多态。
接口每次都要实现,对于已有的代码实现 复用,可通过
委托实现类
。
通过 by
关键字, 来委托接口实现。
举例,Base
接口 委托实现:
interface Base {fun print()
}class BaseImpl(val x: Int) : Base {override fun print() { print(x) }
}// 通过 构造器 参数 委托
class Derived(b: Base) : Base by b
// 也可以 实例对象 委托
class Derived : Base by BaseImpl(10)
二、属性委托(Property delegate)
属性委托,通过 委托类 实现
operator fun getValue(thisRef, property)
operator fun setValue(thisRef, property, value)
方法 实现 委托属性的读写。
下面代码,实现属性委托:
class Delegate(private var str: String) {operator fun getValue(ref: Any?, property: KProperty<*>): String {// 返回 属性值return str}operator fun setValue(ref: Any?, property: KProperty<*>, value: String) {// 进行赋值this.str = value}}class Owner {// 通过委托val p: String by Delegate()
}
方便 属性委托 实现,Kotlin标准库提供:
ReadOnlyProperty
,对应val
只读属性ReadWriteProperty
,对应var
读写属性
属性的委托接口(可手写不使用此接口,仅为了方便)。
public interface ReadWriteProperty<in T, V> : ReadOnlyProperty<T, V> {public override operator fun getValue(thisRef: T, property: KProperty<*>): Vpublic operator fun setValue(thisRef: T, property: KProperty<*>, value: V)}
标准委托
Kotlin 有以下 委托 方法:
- 延迟属性 lazy
- 可观察属性 Delegates.observable 和 Delegates.vetoable
- 委托给其他属性
- Map属性
1. 延迟属性(Lazy properties)
延迟初始化,只有第一次调用时 执行
lazy{}
,后面直接返回 存储的值。
// 延迟属性
val countData by lazy {MutableLiveData(0)
}
2. 可观察属性
每次属性赋值时,都会调用 handler 方法。
vetoable
和 observable
一样也是 赋值 时,调用 handler 方法。
但是 vetoable
是在 赋值前 调用,通过返回 true
false
确定是否 赋值。
// 可观察属性,
val count by Delegates.observable(0) { _, old, new -> println("print value, old: ${old}, new: ${new}")
}
// 是否设置新值 的 可观察属性
val count by Delegates.vetoable(0) { _, old, new -> // 返回false,不更新值false
}
补充:
Delegates
还有 notNull<T>()
方法,创建一个非空的委托,不会在初始化赋值,
而是在后面进行初始值。在设置初始化值前,访问抛出IllegalStateException
异常。
3. 委托给其他属性
将属性 委托 给其他属性 或 其他对象的属性。使用
::
操作符来 引用 其他属性。
class MyClass {var newName: Int = 0@Deprecated("Use 'newName' instead", ReplaceWith("newName"))var oldName: Int by this::newName
}
4. Map委托
通用的场景把 属性值 存储在 map 中。
// Map,取 以 属性名 为 键的 值
class User(val map: Map<String, Any?>) {val name: String by mapval age: Int by map
}// 如果希望可修改,使用 MutableMap
class User(val map: MutableMap<String, Any?>) {var name: String by mapvar age: Int by map
}
文档
- Delegation
- Delegated properties
- kotlincn委托
- Delegation pattern | Wiki