kotlin委托代理讲解

111 阅读3分钟

分以下几类进行讲解

  • 接口委托
  • 延迟委托
  • 引用委托
  • 自定义委托
    • 重写操作符setValue\getValue
    • 实现接口ReadWriteProperty、ReadOnlyProperty
    • 重写操作符provideDelegate

接口委托

  将接口的实现委托给对应传入参数。

interface DB {
    fun save()
}
class SqlDB() : DB {
    override fun save() = println("save to sql")
}
class MySqlDB() : DB {
    override fun save() = println("save to MySqlDB")
}
class OracleDB() : DB {
    override fun save() = println("save to Oracle")
}
// 委托含义解释: 将接口的实现 委托给了参数db
class CreateDBAction(db: DB) : DB by db

fun main() {
    CreateDBAction(SqlDB()).save()
    CreateDBAction(OracleDB()).save()
    CreateDBAction(MySqlDB()).save()
}

延迟委托

  也是我们比较常见的,例如延迟初始化变量,等调用的时候再进行初始化

val lazySqlDB  by lazy { SqlDB() }

引用委托

  之前我们看的2种都是属于直接对象委托,但是我们想委托对应的引用咋整?可以使用双冒号代表引用地址 ::。

// var 可读 可改 内部会有 set get           val 只有get 只读
    var floatValue : Float = 123.45f
        set(v) {
            field = v
            println("你设置了 floatValue哦 v:$v")
        }
        get() {
            println("你获取了 floatValue哦")
            return field
        }

    var number : Float by ::floatValue

自定义委托

重写操作符setValue\getValue

  这个比较好理解,我们变量默认都会实现set\get,如果我们是以类来看,重写类的setValue和getValue

class Owner {
    // var (自定义委托中,必须有 set get)
    // String (自定义委托中,get返回String,set传入String)
    // get/set方法 第一个参数 必须包含 本类Owner或Owner父类
    var text: String by Simple()

    var text2 : String by StringDelegate()
}

class Simple {
    private var str: String = "Default"
    operator fun getValue(owner: Owner, property: KProperty<*>) : String {
        println("getValue执行啦")
        return str
    }

    operator fun setValue(owner: Owner, property: KProperty<*>, value : String) {
        println("setValue执行啦")
        str = value
    }
}

class StringDelegate() : ReadWriteProperty<Owner, String> {
    private var str: String = "Default"
    override fun getValue(thisRef: Owner, property: KProperty<*>): String {
        println("ReadWriteProperty getValue执行啦")
        return str
    }

    override fun setValue(thisRef: Owner, property: KProperty<*>, value: String) {
        println("ReadWriteProperty setValue执行啦")
        str = value
    }
}

fun main() {
    val o = Owner()
    o.text = "自定义simple"
    println(o.text)

    o.text2 = "自定义 delegate"
    println(o.text2)
}

以下是打印的内容

setValue执行啦
setValue执行对应value = 自定义simple
getValue执行啦
自定义simple
ReadWriteProperty setValue执行啦
ReadWriteProperty getValue执行啦
自定义 delegate

  先看Simple,重写操作符operator对应的方法,从而实现自定义委托。ReadWriteProperty是个接口,接口内部实际上也是operator修饰的setValue/getValue,接着往下介绍ReadWriteProperty

实现接口ReadWriteProperty、ReadOnlyProperty

  可以看下ReadWriteProperty、ReadOnlyProperty具体实现,前者是可读可写,后者是只读,前者继承后者

public interface ReadWriteProperty<in T, V> : ReadOnlyProperty<T, V> {

    public override operator fun getValue(thisRef: T, property: KProperty<*>): V

    public operator fun setValue(thisRef: T, property: KProperty<*>, value: V)
}

public fun interface ReadOnlyProperty<in T, out V> {

    public operator fun getValue(thisRef: T, property: KProperty<*>): V
}

  具体源码实现不在本篇内容讲解,来说下ReadWriteProperty具体的参数含义。先说泛型<T,V>,以前面说的StringDelegate作为例子,T(Owner)也就是委托类具体类型,V(String)委托出去的具体类型

class Owner {
    // 把Owner的text2(String类型)委托给StringDelegate
    var text2 : String by StringDelegate()
}

// 第一个泛型被委托的类类型,第二个泛型被委托具体返回的类型
class StringDelegate() : ReadWriteProperty<Owner, String> {

    private var str: String = "Default"

    override fun getValue(thisRef: Owner, property: KProperty<*>): String {
        println("ReadWriteProperty getValue执行啦")
        return str
    }

    override fun setValue(thisRef: Owner, property: KProperty<*>, value: String) {
        println("ReadWriteProperty setValue执行啦")
        str = value
    }
}

   setValue/getValue的第一个参数就是第一个泛型,第二个参数是第二个泛型,这是固定写法。

重写操作符provideDelegate

   重写类自带操作符函数provideDelegate返回类型是ReadWriteProperty,它可以做一个选择器,看一下代码理解

class StringDelegateUpdate(var str: String = "Default") : ReadWriteProperty<Owner2, String> {

    override fun getValue(thisRef: Owner2, property: KProperty<*>): String {
        println("ReadWriteProperty getValue执行啦")
        return str
    }

    override fun setValue(thisRef: Owner2, property: KProperty<*>, value: String) {
        println("ReadWriteProperty setValue执行啦")
        str = value
    }
}

class SmartDelegator {
    // 相当于是一个选择器,动态选择 是哪个 StringDelegateUpdate自定义委托
    operator fun provideDelegate(
        thisRef : Owner2,
        property: KProperty<*>) : ReadWriteProperty<Owner2, String> {

        // 逻辑是自己决定的
        return if (property.name.contains("aaa")) {
            StringDelegateUpdate("bbb")
        } else {
            StringDelegateUpdate("aaa")
        }
    }
}

class Owner2 {
    var aaa: String by SmartDelegator()
    var bbb: String by SmartDelegator()
}

fun main() {
    val owner = Owner2()
    println(owner.aaa)
    println(owner.bbb)
}

  通过重写provideDelegate方法,来决定自己要使用那个ReadWriteProperty对象,从而实现自定义代理选择器