一、Kotlin委托简介
委托模式就是一个对象接收了一条消息,但是自己不处理,转交给别的对象处理。在Kotlin里面通过by关键字直接支持委托模式。
1.1 类委托
类委托就是将一个类接收到消息后,调用另一个类的方法来执行。
interface Animal {
fun walk()
}
class Duck : Animal {
override fun walk() {
println("鸭子摇摆走")
}
}
class BlackDuck(animal: Animal) : Animal by animal
fun main() {
val blackDuck = BlackDuck(Duck())
blackDuck.walk()
}
在上面的这个例子中,BlackDuck
类实现Animal
接口,编译器会生成这个接口的方法,并且在对象内部保存animal
变量。通过by
关键字实现委托,BlackDuck
的方法将调用animal
变量中的方法。
1.2 属性委托
属性委托应该是我们最常见到的委托,by lazy即是一个属性委托。
属性委托的格式:
val/var <属性名>: <类型> by <表达式>
class Furniture {
var category: String by CategoryDelegate()
}
class CategoryDelegate {
operator fun getValue(ref: Any?, property: KProperty<*>): String {
return "haha"
}
operator fun setValue(ref: Any?, property: KProperty<*>, value: String) {
println("$ref 的 ${property.name} 属性赋值为 $value")
}
}
fun main() {
val furniture = Furniture()
furniture.category = "Desk"
println(furniture.category)
}
在by
关键字之后是一个表达式,这个表达式要返回一个委托对象,这个委托对象的类必须要有getValue
方法,如果是var
变量还必须要有setValue
方法。
—ref
是属性所有者对象,这里即是Furniture
对象。
—property
必须是类型 KProperty<*> 或其超类型
—getValue
方法的返回值和setValue
方法的value参数都必须是委托属性的类型,这里即是String
类型。
二、by lazy和lateinit
by lazy
和lateinit
都是Kotlin中的延迟属性初始化方案。by lazy
只能用于val
常量,lateinit
只能应用于var
变量,而var
的基本类型(Long, Int, Float等)只能用Delegates.notNull()
。val
的基本类型还是用by lazy
2.1 by lazy
lazy是一个函数,它接收一个lamda表达式作为参数,返回一个Lazy< T >对象。在没有设置mode的情况下,默认返回SynchronizedLazyImpl
对象,当调用get
方法时,会去调用lamda表达式,并且将lamda表达式的值作为返回值。
private val name: String by lazy {
println("test")
"Duck"
}
2.2 lateinit
private lateinit var category: String
2.3 基本类型变量延迟初始化
private var age: Int by Delegates.notNull()