很多常见属性不是简单的数据,需要每次去手动实现。如果为了方便,可以只写一个类,把他们放进去反复使用是最好的选择。
这里我们使用委托属性。
先看一个例子
class Delegate{
val Hello by lazy{
"HelloWorld"
}
}
当我们调用这个 Hello 的时候,会返回一个字符串 HelloWorld。这个 Hello 只会在第一次调用的时候才赋值。它是使用了 lazy 来实现这个延迟的操作。而观察 lazy 的源码,我们能发现,它有一个 getValue 的函数。
public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
所以 lazy 能够实现取值。
调用方式如下
val delegate = Delegate()
println(delegate.Hello)
而这样的委托,我们也可以自己写出来。
class X {
private var value:String? = ""
operator fun getValue(thisRef: Any?, property: KProperty<*>):String{
println("getValue: $thisRef -> ${property.name}")
return value?:""
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value:String){
println("getValue: $thisRef -> ${property.name} = $value")
this.value = value
}
}
我们建立了一个类,叫 X。实现取值和赋值的操作。
为了看到细节,在赋值和取值的操作代码中,都加入了打印语句。
代码结构是不是很熟悉,是的,我是从 lazy 中抄过来的。不过,X 只支持 String 类型的读写。
然后,在类 Delegate 中增加两个属性。
val Hello2 by X()
var Hello3 by X()
一个常量、一个变量。
常量 Hello2 只能 getValue;变量 Hello3 可以getValue和setValue。
在 main 中我们直接输出,并且在给 Hello3 赋值,看看会发生什么。
val delegate = Delegate()
println(delegate.Hello)
println(delegate.Hello2)
println(delegate.Hello3)
delegate.Hello3 = "顺"
这是完整的运行结果
HelloWorld
getValue: com.cofox.kotlin.Delegate@6ce253f1 -> Hello2
getValue: com.cofox.kotlin.Delegate@6ce253f1 -> Hello3
getValue: com.cofox.kotlin.Delegate@6ce253f1 -> Hello3 = 顺
尤其注意 Hello3,取值和赋值执行的是不同的函数方法。
由此可看出,虽然 delegate 的属性是 Hello2 Hello3,但是真正替代它们起作用的是 X。它的核心实现就是 getValue 和 setValue。
网友评论