2019年7月5日 星期五

Kotlin 的 Delegated Properties (被代理的變數或特性)

參考文章:  https://kotlinlang.org/docs/reference/delegated-properties.html
針對類型裡的特性(propertys), 常數(val)的特性內定 getter 是用 get( ) 方法去讀取主角(field)的值, 對於可寫入的特性(var)而言, 內定 setter 則用 set(v: Type) 方法設定幕後的主角(field), 除非要另外處理 field 的運算才需改寫, 否則 kotlin 會自動加上必要程式碼:
      class SomeClass {
            var   v: String = "?"
                    //  get( ) { return field }
                    //  set(s:String) { field = s }
            val   readonly: Int = 0
                    //  get( ) { return field }
      }
物件在引用特性時不必後綴成對小括號, 因此很簡潔. 物件引用方法( ) 時可以看做是一個運算的結果, 也就是所謂的函數. Kotlin 針對特性或變數有個特別條款可以用 by 跑龍套, 也就是說留待跑龍套代為處置, Koltin  已經為跑龍套主角(object)指定了兩個運算 operator getValue( )  及 operator setValue( ) 來處理特性或變數的讀寫機制, 若想改寫,可以 import pacage 針對讀與寫操作分別作運算,其中對應 get( ) 方法就是 operator getValue( ), 對應  set( ) 方法就是 operator setValue( ), 詳如範例:
import kotlin.reflect.*
class InitString (str: String) { // 代理的主角類型
    var bakendField: String = str  // 真正被讀寫的幕後主角
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
         print(property.name + " : ")
         return bakendField  // return value for method get( ), 讀取
    }
    operator fun setValue(thisRef: Any?, property: KProperty<*>, v: String) {
        println(property.name + " = " + v)
        bakendField = v     // set value to property for method set(v), 寫入
    }
}
fun main(){
    var c : String   by   InitString("???")  // 用物件 InitString( ) 代理改寫變數的讀/寫機制
    println(c)  // 讀取變數 c
    c = "dd"    // 設定變數 c
    println(c)  // 重新讀取變數 c
}
執行結果:
c : ???
c = dd
c : dd

沒有留言: