Following on from our introduction to the by
operator and delegates, this post looks at the second of the five built-in delegates, observable
.
The next built-in delegate is observable
- this allows intercept all attempts to set the value. You can do this with a setter, but remember you would need to duplicate that setter code every time. With the observable, you can build the logic once and reuse it over and over again.
Once again let us start with the way we would do this without the delegated property:
- class User() {
- var name: String = "<NO VALUE>"
- set(value) {
- DataChanged("name", name, value)
- }
- var eyeColour: String = "<NO VALUE>"
- set(value) {
- DataChanged("eyeColour", name, value)
- }
- fun DataChanged(propertyName: String, oldValue: String, newValue: String) {
- println("$propertyName changed! $oldValue -> $newValue")
- }
- }
- fun main(args:Array<String>) {
- val user = User()
- user.name = "Robert"
- user.eyeColour = "Green"
- }
Note, that we need to do the setter manually twice and in each one we will need to change a value, which you know you will get missed when you copy & paste the code.
In the next example, we change to use the observable
delegate which allows us to easily call the same function.
While I don't recommend this for production, I did in the example call it in two different ways. For age
, as the second parameter is a lambda I just create that and pass the parameters to my function. This is how all the demos normally show the usage of this. For name
though, since my function has the same signature as the lambda I can pass it directly to the observable
which seems MUCH nicer to me. Though since we need to pass a reference to our function we need to prefix it with ::
.
- package sadev
- import kotlin.properties.Delegates
- import kotlin.reflect.KProperty
- class User() {
- var name: String by Delegates.observable("<NO VALUE>", ::DataChanged)
- var eyeColour: String by Delegates.observable("<NO VALUE>") { property, old, new ->
- DataChanged(property, old, new)
- }
- fun DataChanged(property: KProperty<*>, oldValue: String, newValue: String) {
- println("${property.name} changed! $oldValue -> $newValue")
- }
- }
- fun main(args:Array<String>) {
- val user = User()
- user.name = "Robert"
- user.eyeColour = "Green"
- }