安卓系列之 kotlin 基础知识(八)

139 阅读2分钟

委托,使用 by 关键字。

委托类

注意点

  1. 委托者重写方法,则调用会优先委托者内的重写方法
  2. 委托者重写属性,则被委托者调用不到委托者内的属性

约束

接口,定义通用的业务功能。

被委托者

类,实现约束接口,实现业务功能的具体执行方法。

委托者

类,传入约束,将约束委托给具体的委托者。

具体场景

委托者:用户
被委托者:外卖员
约束:跑腿买东西

/**
 * 约束
 */
interface IHelpBuyer {
    //送达时间
    val time: Int

    /**
     * 帮忙买东西
     * product--商品
     */
    fun buyThing(product: String)

    /**
     * 传递东西
     * thing--东西
     * receiverName--签收者姓名
     */
    fun carryThing(thing: String, receiverName: String)
}

/**
 * 被委托对象
 * 美团小哥
 */
class MeiTuanXiaoGe(val name: String) : IHelpBuyer {
    override val time = 20
    override fun buyThing(product: String) {
        print("MeiTuan,$name need to buy the $product for the client in $time.")
    }

    override fun carryThing(thing: String, receiverName: String) {
        print("MeiTuan,$name need to carry the $thing for $receiverName in $time.")
    }

}

/**
 * 被委托对象
 * 饿了么小哥
 */
class EleMeXiaoGe(val name: String) : IHelpBuyer {
    override val time = 30
    override fun buyThing(product: String) {
        print("EleMe,$name need to buy the $product for the client in $time.")
    }

    override fun carryThing(thing: String, receiverName: String) {
        print("EleMe,$name need to carry the $thing for $receiverName in $time.")
    }

}

/**
 * 委托对象
 * 用户
 */
class User(val helpBuyer: IHelpBuyer) : IHelpBuyer by helpBuyer {
    override val time: Int
        get() = 60
    /**
     * 重写了传递东西的方法
     */
    override fun carryThing(thing: String, receiverName: String) {
        print("Me need to carry the $thing for $receiverName in $time.")
    }
}

/**
 * 使用
 */
fun testHelpBuyer() {
    //美团小哥Tony
    val meiTuanXiaoge1 = MeiTuanXiaoGe("Tony")
    //饿了么小哥Alice
    val eleMeXiaoGe1 = EleMeXiaoGe("Alice")
    //用户1需要买coffee
    val buyer1 = User(meiTuanXiaoge1)
    buyer1.buyThing("coffee")
    //用户2需要买fish
    val buyer2 = User(eleMeXiaoGe1)
    buyer2.buyThing("fish")

    //覆盖由委托实现的接口成员,则会执行委托对象里面的重写方法
    val buyer3 = User(meiTuanXiaoge1)
    buyer3.carryThing("gift""Lily")
    //在委托者中重写的属性,不会被被委托者使用
    print(buyer3.time)

}

委托属性

格式

val/var <属性名>: <类型> by <表达式>

  1. val 只需要 getValue(),系统提供了 ReadOnlyProperty<in T, out V>
  2. var 需要 setValue()和 getValue() ,系统提供了 ReadWriteProperty<in T, V>

使用例子

class Example {
    var p: String by Delegate()
    val m: String by Delegate2()
    var n: String by Delegate3()
}

/**
 * 属性委托
 * var ---需要一个setValue和getValue方法
 * val ---只需要getValue方法
 */
class Delegate {
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }

    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }
}

//val 只读
class Delegate2 : ReadOnlyProperty<Any, String> {
    override fun getValue(thisRef: Any, property: KProperty<*>): String {
        return "ReadOnlyProperty====,name:${property.name}"
    }
}

//var 可读可写
class Delegate3 : ReadWriteProperty<Any, String> {
    override fun getValue(thisRef: Any, property: KProperty<*>): String {
        return "ReadWriteProperty====,name:${property.name}"
    }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: String) {
        println("ReadWriteProperty====, name:${property.name} value: $value")
    }
}

fun testExample() {
    val p = Example()
    print(p.p)//Example@33a17727, thank you for delegating ‘p’ to me!
    p.p = "NEW"//NEW has been assigned to ‘p’ in Example@33a17727.

    val m = Example()
    print(m.m)//ReadOnlyProperty====,name:m

    val n = Example()
    print(n.n)//ReadWriteProperty====,name:n
    n.n = "NEW"//ReadWriteProperty====, name:n value:NEW
}

标准库中的委托

lazy

延迟属性,只有在第一次调用的时候才会初始化值。

//by lazy
// 第一次调用的时候会初始化,第二调用直接使用值
val myLazy by lazy {
    print("This is First.")
    "myLazy==="
}

fun testMyLazy() {
    println(myLazy)//This is First.myLazy===
    println(myLazy)//myLazy===
}

Observable

可观察属性,可以看到值的变化过程。

//Observable 可以观察到数据的变化
var myObservableValue by Delegates.observable("无") { property, oldValue, newValue ->
    print("property,$oldValue,$newValue")
}

fun testMyObservableValue() {
    myObservableValue = "1111"//property,无,1111
    myObservableValue = "2222"//property,1111,2222
}

vetoable

截获赋值并“否决”它们。

//vetoable 通过比较来决定新传入的值是否有效
var myVetoableValue: Int by Delegates.vetoable(1) { _, oldValue, newValue ->
    newValue > oldValue
}

fun testMyVetoableValue() {
    myVetoableValue = 2//2
    myVetoableValue = 5//5
    myVetoableValue = 3//5
}

把多个属性储存在一个映射

使用 map 或者 mutableMap 映射存储值

//map 把属性储存在映射中
class Cup(private val map: Map<String, Any?>) {
    val color: String by map
    val capacity: Int by map
}

fun testCup() {
    val cup = Cup(mapOf("color" to "red""capacity" to 500))
    print("$cup.color cup has ${cup.capacity} ml."//red cup has 500 ml.
}

项目 github 地址

github.com/ElaineTaylo…

若帅哥美女对该系列文章感兴趣,可微信搜索公众号(木子闲集)关注更多更新文章哦,谢谢~