Step into Kotlin - 24 - delegate

目录

摘要

类的委托,属性的委托,Lazy Properties,Observable Properties,Not Null,Map Val

Delegate

类的委托

类的委托使用 by 语句

创建接口和子类

interface Base {
    fun println()
}

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

建立委托类

class Derived(b: Base) : Base by b

以上 Derived 类 创建了所有来自 Base 的方法,并且委托一个传入的 Base 的对象 执行这些方法。

使用委托类

val b = BaseImpl(19)
b.println() //  19
Derived(b).println()    //  19

属性的委托

创建被委托类

class Delegate {
    fun get(thisRef: Any?, prop: PropertyMetadata): String {
        return "$thisRef, thank you for delegating '${prop.name}}' to me!"
    }

    fun set(thisRef: Any?, prop: PropertyMetadata, value: String) {
        println("$value has been assigned to '${prop.name} in $thisRef.'")
    }
}

创建委托类

class Example {
    var p: String by Delegate()
}

使用委托

val e = Example()
println(e.p)
e.p = "NEW"

内置属性委托

分类

Kotlin API 中有两种标准的属性委托方法,一种是 lazy properties,一种是 observable properties。

Lazy Properties
  • Lazy Properties 在第一次被访问时才会获取值。
  • Lazy Properties 是通过 lazy 方法来实现的。
  • lazy 方法接收一个Lambda 表达式,在第一次执行时会计算 Lambda 的值然后存储起来,之后访问的话会直接取得保存的值,而不会重新计算。
val lazy: String by lazy {
    println("computed!")
    "Hello ${System.currentTimeMillis()}"
}

println("lazy is ${lazy}")
println("lazy is ${lazy}")

lazy 是非线程安全的,线程安全的版本见下面的例子

val blockLazy: String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
    println("computed2!")
    "Hello2 ${System.currentTimeMillis()}"
}
Observable Properties
  • Observable Properties 被存储在一个 Map 中,而不是单独的属性。
  • Observable Properties 可以设置监听值改变事件的监听器。
  • Observable Properties 是通过 observable()方法实现的。
  • observable()方法接收两个参数,第一个为初始值,第二个为监听的回调Handler,该 Handler 接收三个参数:被设置的属性,旧值,新值。
class User {
    var name: String by Delegates.observable("<no name>") {
        d, old, new ->
        println("$old -> $new")
    }
}

val user = User()
user.name = "first"
user.name = "second"

也可以使用 vetoable() 代替 observable(),该方法功能类似,但是返回布尔值,用以表示这次设置是否有效。

class User {
    var age: Int by Delegates.vetoable(0) {
        d, old, new ->
        println("$old -> $new")
        if (new < 20) true else false
    }
}

val user = User()
user.age = 10
println(user.age)
user.age = 20
println(user.age)

Not Null

由于 Kotlin 不允许定义任何非空的非抽象属性,但是实际使用时可能也需要定义这样的属性,这时就需要 not null 方法来实现。

class NotNullFoo {
    var bar: String by Delegates.notNull()
}

val foo = NotNullFoo()
foo.bar = "bar"

Map Val

Map Val 可以用于将所有属性保存在一个 Map 中,在使用 JSON 等数据格式或者实现某些动态特性时这种功能很有用。

class Account(val map: Map<String, Any?>) {
    val name: String by Delegates.mapVal(map) {
        o, p ->
        println("$o -> $p")
        "default name"
    }
    val age: Int by Delegates.mapVal(map) {
        o, p ->
        println("$o -> $p")
        0
    }
}

val account = Account(mapOf(
        "name" to "John",
        "age" to 25
))
println(account.name)
println(account.age)

mapVar()为以上的可变版本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值