美文网首页
83.Kotlin 委托 by

83.Kotlin 委托 by

作者: SlideException | 来源:发表于2020-08-22 23:29 被阅读0次

    https://www.jianshu.com/p/a70ba6436e75/
    https://www.jianshu.com/p/306bdc2bac3f
    代理模式:为其他对象提供一种代理以控制其他对象对这个对象的访问。

    委托属性的声明

    定义一个委托属性的语法是 val/var <property name>: <Type> by <expression>,其中 by 后面的就是属性的委托。属性委托不用继承什么特别的接口,只要拥有用 operator 修饰的 getValue() 和 setValue() (适用 var)的函数就可以了。

    by lazy的必须用val修饰

    类委托

    一个类中定义的方法实际是调用另一个类的对象的方法来实现的。

    //创建接口
    interface Base {   
        fun print()
    }
    //实现此接口的被委托的类
    class BaseImpl(val x: Int) : Base {
        override fun print() { print(x) }
    }
    //通过关键字 by 建立委托类
    class Derived(b: Base) : Base by b
    //测试
    fun main(args: Array<String>) {
        val b = BaseImpl(10)
        Derived(b).print() // 输出 10
    }
    

    在 Derived 声明中,by 子句表示,将 b 保存在 Derived 的对象实例内部,而且编译器将会生成继承自 Base 接口的所有方法, 并将调用转发给 b。

    属性委托

    属性委托是指一个类的某个属性值不是在类中直接进行定义,而是将其托付给一个代理类,从而实现对该类的属性统一管理。
    val/var 变量名:类型 by 表达式
    by字之后的表达式就是委托,属性的get set方法将被委托给这个对象的setVaule getValue方法,属性委托不必实现任何接口,但必须提供getValue setValue函数。

    import kotlin.reflect.KProperty
    // 定义包含属性委托的类
    class Example {
        var p: String by Delegate()
    }
    // 委托的类
    class Delegate {
        //setValue getValue方法的修饰符 方法名 参数类型 只能这么写
        operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
            return "$thisRef, 这里委托了 ${property.name} 属性"
        }
        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
            println("$thisRef 的 ${property.name} 属性赋值为 $value")
        }
    }
    fun main(args: Array<String>) {
        val e = Example()
        println(e.p)     // 访问该属性,调用 getValue() 函数
    
        e.p = "Runoob"   // 调用 setValue() 函数
        println(e.p)
    }
    输出结果为:
    Example@433c675d, 这里委托了 p 属性
    Example@433c675d 的 p 属性赋值为 Runoob
    Example@433c675d, 这里委托了 p 属性
    

    标准委托

    Kotlin的标准库中已经内置了很多工厂方法来实现属性委托。

    延迟属性lazy

    lazy()是一个函数,接受一个lambda表达式作为参数,返回一个lazy<T>实例的函数,返回的实例可以作为实现延迟属性的委托:第一次调用get方法会执行已传递给lazy的lambda表达式并记录结果,后续调用get方法只是返回记录的结果。

    val lazyValue: String by lazy {
        println("computed!")     // 第一次调用输出,第二次调用不执行
        "Hello"
    }
    fun main(args: Array<String>) {
        println(lazyValue)   // 第一次执行,执行两次输出表达式
        println("--------")
        println(lazyValue)   // 第二次执行,只输出返回值
    }
    执行输出结果:
    computed!
    Hello
    --------
    Hello
    

    get方法是线程不安全的,lazy是线程安全的,
    。。。后面还一个例子看文章。

    相关文章

      网友评论

          本文标题:83.Kotlin 委托 by

          本文链接:https://www.haomeiwen.com/subject/lbbujktx.html