kotlin的几种委托机制

kotlin

Posted by MetaNetworks on January 4, 2021
本页面总访问量

委托机制中的三个角色

  • 约束:通常是接口、抽象类,也是被代理的业务
  • 被委托对象:具体业务的逻辑执行者
  • 委托对象:负责对真实角色的应用,将约束类定义的业务委托给具体的委托对象

类委托(标准的静态代理模式)

假设有这么一段代码

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重载了getValuesetValue方法。

假定有属性var item: String by Delegates.NotNull(),当调用item的值或者item = "xxx"时,代理类的getValuesetValue方法被调用。若为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时,代理类WeaksetValue被调用,传入弱引用。