Step into Kotlin - 24 - delegate

来源:互联网 发布:英语发音自测软件 编辑:程序博客网 时间:2024/05/16 10:41

目录

    • Delegate
      • 类的委托
      • 属性的委托
      • 内置属性委托
        • 分类
        • Lazy Properties
        • Observable Properties
      • Not Null
      • Map Val

摘要

类的委托,属性的委托,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() //  19Derived(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 = 10println(user.age)user.age = 20println(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
原创粉丝点击