Kotlin之代理

package cn.zms.class2

import kotlin.properties.Delegates
import kotlin.reflect.KProperty

/**
 * 类代理:by关键字
 * 属性代理:val/var :  by 
 */
interface Base{
    fun print()
}

class BaseImpl(var x: Int) : Base{
    override fun print(){
        println(x)
    }
}

//类代理,通过“by”关键字,将“b”实例存储到Derived对象中,编译器会生成“Base”接口的所有方法,使用“b”的实现。
class Derived(b: Base) : Base by b


//属性代理
class Example {
    //语法:val/var :  by 
    var p: String by DelegateTheP()
}

class DelegateTheP {
    //属性代理不需要实现任何接口,只需要提供getValue() setValue()【val属性不需要】函数
    /**
     * thisRef p所属的Example实例
     * property p实例本身的描述信息
     */
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name} in $thisRef.'")
    }
}


class UserPropertyByDelegate(val map: Map) {
    val name: String by map
    val age: Int     by map
}

class UserPropertyByDelegate2(val map: MutableMap) {
    //var的属性代理,请使用MutableMap对象
    var name: String by map
    var age: Int     by map
}


fun main(args: Array) {
    //======================1.类代理======================
    val b = BaseImpl(10)
    Derived(b).print()
    //======================2.属性代理======================
    val e = Example()
    //读取p访问DelegateTheP.getValue()
    println(e.p)
    //p的赋值会调用DelegateTheP.setValue()
    e.p = "123"

    //======================标准属性代理之:Lazy======================
    /**
     *  默认Lazy属性是线程同步的(synchronized),
     *  如果不需要synchronized可以将lazy()构造函数中传入LazyThreadSafetyMode.PUBLICATION,那么多个线程可以同时赋值
     *  如果可以确保属性只会在单线程中初始化,可以lazy()构造函数中传入LazyThreadSafetyMode.NONE,以节省线程开销
     */
    val  lazyValue : String by lazy(){
        //第一次访问,初始化,然后保存,相当于单例模式
        println("Completed")
        "Hello"
    }
    //只有第一次打印才会
    println(lazyValue)
    println(lazyValue)

    //======================标准属性代理之:Observable======================
    //两个参数,初始化的值,修改值时的回调函数大括号中
    var name: String by Delegates.observable("") {
        prop, old, new ->
        println("$old -> $new")
    }
    name = "first"
    name = "second"
    println(name)

    //当需要拦截修改事件,并只能判断是否允许修改,可以使用vetoable代理
    var nameVeto: String by Delegates.vetoable("") {
        prop, old, new ->
        println("$old -> $new")
        //要有返回值,代表是否允许修改,当second赋值时才能修改
        new == "second"
    }
    nameVeto = "first"
    println(nameVeto)
    nameVeto = "second"
    println(nameVeto)

    //======================标准属性代理之:Storing Properties in a Map======================
    /**
     * 你肯定会经常使用使用Map来存储属性,常见的场景是当需要解析JSON值或其他动态的事情。
     * 这时就可以使用Map对象为代理属性提供代理
     */

    var user = UserPropertyByDelegate(mapOf(
            "name" to "john",
            "age"  to  15
    ))
    println("${user.name} age is ${user.age}")


    //======================3.局部变量代理(since 1.1)======================
    //局部变量同样也可以使用代理
}

你可能感兴趣的:(Kotlin)