Kotlin Vocabulary _ Kotlin 内建代理,程序员35岁真的是分水岭吗

Observable

Delegates.observable() 是另一个 Kotlin 标准库中内建的代理。观察者模式是一种设计模式,在这一模式中,一个对象会维护一个它的从属者的列表,这些从属者即被称为观察者。对象会在它自己的状态改变时对观察者进行通知。这一模式十分契合多个对象需要在某个值发生改变时得到通知的情况,可以避免实现为从属对象周期调用和检查资源是否更新。

observable() 函数接收两个参数: 初始化值与一个当值发生改变时会被调用的监听处理器。observable() 会创建一个 ObservableProperty 对象,用于在每次 setter 被调用时执行您传给代理的 lambda 表达式。

class Person {
var address: String by Delegates.observable(“not entered yet!”) {
property, oldValue, newValue ->
// 执行更新操作
}
}

通过观察反编译后的 Person 类型,我们可以看到 Kotlin 编译器生成了一个继承 ObservableProperty 的类。这个类同时也实现了一个叫做 afterChange() 的函数,这个函数持有您传递给 observable 代理的 lambda 函数。

protected void afterChange(@NotNull KProperty property, Object oldValue, Object newValue) {
// 执行更新操作
}

afterChange() 函数由父 ObservableProperty 类的 setter 调用,这意味着每当调用者为 address 设置一个新的值,setter 就会自动调用 afterChange() 函数,结果就会使所有的监听器都会收到有关改变的通知。

class Person {
var address: String by Delegates.observable(“not entered yet!”) {
property, oldValue, newValue ->
// 执行更新操作
}
}

您还可以从反编译后的代码中看到 beforeChange() 函数的调用,observable 代理不会使用 beforeChange()。但对于您接下来会看到的 vetoable(),这一函数却是功能实现的基础。

vetoable

vetoable() 是一个内建代理,属性将否决权委托给它的值。与 observable() 代理类似,vetoable() 同样接受两个参数: 初始值与监听器,当任何调用者想要修改属性值时,监听器就会被调用。

var address: String by Delegates.vetoable(“”) {
property, oldValue, newValue ->
newValue.length > 14
}

如果 lambda 表达式返回 true,属性值就会被修改,反之则保持不变。在本例中,如果调用者尝试使用长度小于 15 个字符的字符串来更新地址的话,当前值就不会发生改变。

观察反编译后的 Person 可以发现,Kotlin 新生成了一个继承 ObservableProperty 的类,该类中包含了我们传入 beforeChange() 函数的 lambda 表达式,setter 会在每次值被设置之前调用 lambda 表达式。

public final class Person s p e c i a l special specialinlined$vetoable$1 extends ObservableProperty {

protected boolean beforeChange(@NotNull KProperty property, Object oldValue, Object newValue) {
Intrinsics.checkParameterIsNotNull(property, “property”);
String newValue = (String)newValue;
String var10001 = (String)oldValue;
int var7 = false;
return newValue.length() > 14;
}
}

notNull

Kotlin 标准库中所提供的最后一个内建代理是 Delegates.notNull()notNull() 允许一个属性可以延后一段时间初始化,与 lateinit 类似。由于 notNull() 会为每个属性创建额外的对象,所以大多数情况下推荐使用 lateinit。不过,您可以将 notNull() 与原生类型一同使用,这点是 lateinit 所不支持的。

val fullname: String by Delegates.notNull()

notNull() 使用一种特殊类型的 ReadWriteProperty: NotNullVar。

我们可以查看反编译后的代码,下面的例子中使用 notNull() 函数初始化了 fullname 属性:

this.fullname$delegate = Delegates.INSTANCE.notNull();

该函数返回了一个 NotNullVar 对象:

public fun  notNull(): ReadWriteProperty<Any?, T> = NotNullVar()

NotNullVar 类型持有一个泛型的可空内部引用,如果在初始化值之前有任何代码调用 getter,则抛出 IllegalStateException()

  • 19
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值