委托机制中的三个角色
- 约束:通常是接口、抽象类,也是被代理的业务
- 被委托对象:具体业务的逻辑执行者
- 委托对象:负责对真实角色的应用,将约束类定义的业务委托给具体的委托对象
类委托(标准的静态代理模式)
假设有这么一段代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface Base {
fun show()
}
open class BaseImpl : Base {
override fun show() {
Log.d("base", "show")
}
}
class BaseProxy(base: Base) : Base by base {
fun showOther() {
AbLogUtil.e("BaseImpl::showOther()")
}
}
代理类BaseProxy通过by
代理了base,拥有了base的方法show()的实现,且还有showOther方法。
retrofit为典型的动态代理模式,在运行时生成代理类
属性委托
来看官方Delegates
类定义的三种属性委托
Delegates.notNull
- 由
ReadWriteProperty
子类NotNullVar
完成
- 由
1
2
3
4
5
6
7
8
9
10
11
private class NotNullVar<T : Any>() : ReadWriteProperty<Any?, T> {
private var value: T? = null
public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value ?: throw IllegalStateException("Property ${property.name} should be initialized before get.")
}
public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
}
}
其中,NotNullVar重载了getValue
和setValue
方法。
假定有属性var item: String by Delegates.NotNull()
,当调用item
的值或者item = "xxx"
时,代理类的getValue
和setValue
方法被调用。若为null则由代理类throw出exception.
-
Delegates.observable
-
由代理类进行值的监听,具体代码如下:
-
KProperty<*>
-
用于描述属性
-
题外话[泛型]:
*
与Any
不同,*
为语法糖,对应着<out Any?>
,对应着java中的写法<?>
或<? extends Object>
,为上界通配符,只可输出不可输入(比如val list: MutableList<*> = mutableListOf(1, "nanchen2251")
不支持add
,将*
改为Any?
后就可以了)。<in Any?>
对应着java中的写法<? super Any>
,为下界通配符,只可输入不可输出。-
Extends
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
interface Fruit { val weight: Float } internal class Banana : Fruit { override val weight: Float get() = 0.5f } internal class Apple : Fruit { override val weight: Float get() = 1f } interface Shop<T> { fun showFruitName(t: T) fun getFruit(): T } val appleShop: Shop<out Fruit> = object : Shop<Apple> { override fun showFruitName(t: Apple) { } override fun getFruit(): Apple { return Apple() } } // 以下代码报错,out为只输出不输入,即无法传入任何Fruit及子类 appleShop.showFruitName(Apple())
-
super
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
interface Fruit { val weight: Float } internal class Banana : Fruit { override val weight: Float get() = 0.5f } internal class Apple : Fruit { override val weight: Float get() = 1f } interface Shop<T> { fun showFruitName(t: T) fun getFruit(): T } val appleShop: Shop<in Apple> = object : Shop<Fruit> { override fun showFruitName(t: Fruit) { } override fun getFruit(): Fruit { return object : Fruit{ ... } } } appleShop.showFruitName(new Apple()); // 以下代码报错,appleShop.getFruit()会返回Any?类型,直接把可能为父类的类赋值到子类apple是有问题的 Apple apple = appleShop.getFruit();
-
-
-
-
1
2
3
4
5
public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
ReadWriteProperty<Any?, T> =
object : ObservableProperty<T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
}
若值发生更改,onChange
方法被调用,将新旧值返回给观察者。
1
2
3
var baseItem : Base by Delegates.observable(BaseImpl()){ kProperty: KProperty<*>, base: Base, base1: Base ->
print("item changed")
}
当对baseItem
赋值时,lambda表达式中的print被执行
Delegates.vetoable
- 可用于判断是否接收更新的新值
除此之外,lazy
也值得关注。lazy
用于懒加载,对于一个值
1
2
3
private val name : String by lazy {
"MetaNetworks"
}
只有访问时,name
才被赋值为MetaNetworks
应用
可以使用委托来封装某个属性的一些逻辑,如判空等等
此处封装一个弱引用代理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Weak<T : Any>(initializer: () -> T?) : Base {
var value = WeakReference<T?>(initializer())
constructor() : this({
null
})
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
Log.d("get","value from delegate.")
return value.get()?: throw IllegalStateException("get value error")
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
Log.d("set","value from delegate.")
this.value = WeakReference(value)
}
override fun show() {
}
}
当获取值时为null就抛出异常。
定义一个属性
1
2
3
var baseItem : Base by Weak()
baseItem
baseItem = BaseImpl()
当执行baseItem时,代理的getValue
执行。当baseItem
被赋值为新的BaseImpl时,代理类Weak
的setValue
被调用,传入弱引用。