2016-10-04 76 views

回答

26

雖然科特林不提供內置的屬性更改觀察斯威夫特式的解決方案,你仍然可以做它取決於你的目標是什麼幾種方法。

  • observable(...)代表(in stdlib),使您可以處理財產的變化。用例:

    var foo: String by Delegates.observable("bar") { property, old, new -> 
        println("$property has changed from $old to $new") 
    } 
    

    這裏,"bar"是財產foo初始值,拉姆達被稱爲每次屬性分配後,可以讓你觀察changes.There的也vetoable(...) delegate,使您可以防止改變。

  • 可以使用custom setter的財產實際價值變動前後執行任意代碼/:

    var foo: String = "foo" 
        set(value: String) { 
         baz.prepareToDoTheThing() 
         field = value 
         baz.doTheThing() 
        } 
    

    作爲@KirillRakhman指出,這種解決方案是非常有效的,因爲它引入了在方法調用沒有開銷和對象,儘管在多個屬性的情況下代碼會有點重複。

  • 一般情況下,你可以實現自己的property delegate,明確規定在getValue(...)setValue(...)功能財產的行爲。

    要簡化你的任務,使用​​抽象類,它可以讓你實現一個觀察屬性更改(如observable及以上vetoable)實例代表:

    var foo: String by object : ObservableProperty<String>("bar") { 
        override fun beforeChange(property: KProperty<*>, oldValue: String, newValue: String): Boolean { 
         baz.prepareToDoTheThing() 
         return true // return false if you don't want the change 
        } 
    
        override fun afterChange(property: KProperty<*>, oldValue: String, newValue: String) { 
         baz.doTheThing() 
        } 
    } 
    

    爲了您的方便,你可以寫一個創建函數委託對象:

    fun <T> observing(initialValue: T, 
            willSet:() -> Unit = { }, 
            didSet:() -> Unit = { } 
    ) = object : ObservableProperty<T>(initialValue) { 
        override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = 
          true.apply { willSet() } 
    
        override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = didSet() 
    } 
    

    然後你只需通過lambda表達式以它爲willSetdidSetthe default argument他們是{ })。用法:

    var foo: String by observing("bar", willSet = { 
        baz.prepareToDoTheThing() 
    }, didSet = { 
        baz.doTheThing() 
    }) 
    
    var baq: String by observing("bar", didSet = { println(baq) }) 
    

在任何情況下,它是由你來確保觀察變化的代碼不會再設置該屬性,因爲它很可能會陷入無限遞歸,否則你可能會檢查它在觀察代碼中是否遞歸調用setter。

+0

令人驚訝的是,第二種方法恰恰是我在建立之間建立的一種解決方法,問你答案! :D – Supuhstar

+1

@Supuhstar,很高興你走對了。:) – hotkey

+2

@hotkey您應該詳細說明自定義設置器,因爲它是實現它的最有效方法。 –

相關問題