What are the use cases for `Delegates.observable` when we have property setters?
Asked Answered
I

2

29

What are the use cases for Delegates.observable when we can just use property setters?

 var foo by Delegates.observable("hell0") { prop, old, new ->
    // react to changes in foo
  }

  var bar = "hello"
    set(value) {
      field = value
      // react to changes in bar
      // we can also do validation, set something like `value*2` to field, etc.
    }
Ivelisseivens answered 21/4, 2018 at 21:55 Comment(0)
T
26

Property setters require much more code duplication if you want multiple properties to react to modification in the same way:

var foo: Foo = Foo()
    set(value) {
        println("foo = $value")
        field = value
    }

var bar: Bar = Bar()
    set(value) {
        println("bar = $value")
        field = value
    }

Delegates, in turn, are aimed to allow for reuse of the property accessors logic, like this:

fun <T> printDelegate(init: T) = 
    Delegates.observable(init) { prop, _, new ->
        println("${prop.name} = $new")
    }

val foo: Foo by printDelegate(Foo())
val bar: Bar by printDelegate(Bar())
Therapeutic answered 21/4, 2018 at 22:4 Comment(1)
logic reuse is also possible (albeit in a more limited way) with property setters. The key difference is that Delegates.observable() provides access to the property (and oldValue) being observed.Correspond
E
-2

Delegates.observable are commonly used in Android. One such such case is adding text change listener.

Example

interface TextChangedListener {
    fun onTextChanged(newText: String)
}

class PrintingTextChangedListener : TextChangedListener {
    override fun onTextChanged(newText: String) = println("Text is changed to: $newText")
}

class TextView {

    var listener: TextChangedListener? = null

    var text: String by Delegates.observable("") { prop, old, new ->
        listener?.onTextChanged(new)
    }
}

Usage

val textView = TextView()
textView.listener = PrintingTextChangedListener()
textView.text = "Lorem ipsum"
textView.text = "dolor sit amet"

Output

Text is changed to: Lorem ipsum

Text is changed to: dolor sit amet

You can read more patterns here: https://github.com/dbacinski/Design-Patterns-In-Kotlin

Earthworm answered 17/7, 2018 at 8:59 Comment(1)
This doesn't answer why it's preferable to set(value) { field = value; listener?.onTextChanged(value) } (the actual question).Ushijima

© 2022 - 2024 — McMap. All rights reserved.