很多常見(jiàn)屬性不是簡(jiǎn)單的數(shù)據(jù)古毛,需要每次去手動(dòng)實(shí)現(xiàn)钦购。如果為了方便檐盟,可以只寫一個(gè)類,把他們放進(jìn)去反復(fù)使用是最好的選擇押桃。
這里我們使用委托屬性葵萎。
先看一個(gè)例子
class Delegate{
val Hello by lazy{
"HelloWorld"
}
}
當(dāng)我們調(diào)用這個(gè) Hello 的時(shí)候,會(huì)返回一個(gè)字符串 HelloWorld。這個(gè) Hello 只會(huì)在第一次調(diào)用的時(shí)候才賦值羡忘。它是使用了 lazy 來(lái)實(shí)現(xiàn)這個(gè)延遲的操作谎痢。而觀察 lazy 的源碼,我們能發(fā)現(xiàn)卷雕,它有一個(gè) getValue 的函數(shù)节猿。
public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
所以 lazy 能夠?qū)崿F(xiàn)取值。
調(diào)用方式如下
val delegate = Delegate()
println(delegate.Hello)
而這樣的委托漫雕,我們也可以自己寫出來(lái)滨嘱。
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
}
}
我們建立了一個(gè)類,叫 X浸间。實(shí)現(xiàn)取值和賦值的操作太雨。
為了看到細(xì)節(jié),在賦值和取值的操作代碼中魁蒜,都加入了打印語(yǔ)句囊扳。
代碼結(jié)構(gòu)是不是很熟悉,是的兜看,我是從 lazy 中抄過(guò)來(lái)的锥咸。不過(guò),X 只支持 String 類型的讀寫细移。
然后搏予,在類 Delegate 中增加兩個(gè)屬性。
val Hello2 by X()
var Hello3 by X()
一個(gè)常量葫哗、一個(gè)變量缔刹。
常量 Hello2 只能 getValue;變量 Hello3 可以getValue和setValue劣针。
在 main 中我們直接輸出校镐,并且在給 Hello3 賦值,看看會(huì)發(fā)生什么捺典。
val delegate = Delegate()
println(delegate.Hello)
println(delegate.Hello2)
println(delegate.Hello3)
delegate.Hello3 = "順"
這是完整的運(yùn)行結(jié)果
HelloWorld
getValue: com.cofox.kotlin.Delegate@6ce253f1 -> Hello2
getValue: com.cofox.kotlin.Delegate@6ce253f1 -> Hello3
getValue: com.cofox.kotlin.Delegate@6ce253f1 -> Hello3 = 順
尤其注意 Hello3鸟廓,取值和賦值執(zhí)行的是不同的函數(shù)方法。
由此可看出襟己,雖然 delegate 的屬性是 Hello2 Hello3引谜,但是真正替代它們起作用的是 X。它的核心實(shí)現(xiàn)就是 getValue 和 setValue擎浴。