委托类
实现一个接口,可以使用by关键字将接口实现委托给另一个对象。
类委托后我们依然可以通过重写的方式来覆盖委托类的实现,这里View实现onLongClick方法,覆盖重写了ViewClickDelegate类里的onLongClick方法。
类委托的本质是:把抽象方法的实现交给了by后的委托对象
延迟初始化和委托属性
延迟初始化属性
不在对象创建的时候初始化,而是在第一次使用时初始化。完成后像普通属性一样使用
惰性初始化属性
第一次使用该属性时才初始化,且只初始化一次。用旗号标示是否初始化过,旗号有多种选择和实现方式。
在代码定义处执行初始化,有助于代码维护。
对指令式语言,这个模式可能潜藏着危险,尤其是使用共享状态的程式习惯。
普通实现
by lazy(){}实现惰性初始化
在JavaBean的设计中,按照属性的不同作用又细分为四类:单值属性,索引属性;关联属性,限制属性。接下来看下Kotlin如何实现关联属性和限制属性的
关联属性(可观察属性)
通过PropertyChangeSupport代码实现属性监听
把逻辑封装,抽取出基类
把book里的set访问器的逻辑封装成一个类
至此,我们用Kotlin手工实现了可观察属性变化的功能,测试下
运行上述代码结果如下:
old book = Book(name=Think in java) , new book = Book(name=Kotlin in action)
使用Kotlin委托实现
Kotlin的委托属性在语言层面提供了在属性的读访问器里调用委托类里operator修饰的两参数getValue方法,属性写访问器调用operator修饰setValue三个参数方法
通常借助ReadWriteProperty接口能方便我们实现委托
测试上述代码:
运行结果如下:
Kotlin委托 old book is Book(name=Think in java), and new book is Book(name=Kotlin in action!)
委托属性的本质:把属性访问器的实现交给了by后的委托对象
使用Kotlin的自带的实现可观察属性
其实,Delegate.observable()类实现了上面提到的所有逻辑了。
我们看下Delegate.observable方法的源码
该方法返回ObservableProperty对象,看下ObservableProperty对象源码
该对象有getValue和setValue方法,这和我们自己实现的BookDelegate3类里的getValue和setValue方法逻辑几乎相同。不同之处是,官方还多了beforeChange()控制,和afterChange()供实现类覆盖重写。
Kotlin标准库已经提供了可观察属性的属性委托实现了
测试下上述的代码
运行结果如下
The old book's name is "think in java", and the new book's name is "Kotlin in action"
限制属性
Kotlin也为我们提供了现成的委托类来实现限制属性
测试上述代码
运行结果如下:
current book is 0
current book is 20
注意:上述用的是成员函数,事实上,扩展函数也能实现委托属性
使用Map实现委托属性
MapAccessors.kt文件里,有如下扩展函数源码
由此可见, MutableMap存在getValue方法和setValue方法,那么就可以用于委托,事实上,也确实如此。
举个例子:
运行结果
color = 绿色, size = 2kg
小结
类委托的本质是:把抽象方法的实现交给了by后的委托对象
属性委托的本质是:把属性访问器的实现交给了by后的委托对象
扩展函数也能实现属性委托
参考资料
维基百科:惰性初始化模式
维基百科:惰性求值
领取专属 10元无门槛券
私享最新 技术干货