Home > OS >  Var recalculation after content change
Var recalculation after content change

Time:09-16

I just started learning Kotlin and could not get one thing:

I have a variable that is based on some other variables (for example "A" and "B"). Is there an easy way to recalculate the resulted variable after i change var "A" or "B"? As i understood, i can just repeat the code for "result" again, but is there an easier way? i think in some cases the code could be quite long...

Example is below:

var valueA = 9
var valueB = 10
var result = valueA*valueB
println(result)

valueA = 15

"A" is changed, but if i write "println(result)" right now, var "result" will not be recalculated and will stay = 90

result = valueA*valueB
println(result)

only after i write the same code for "result" again, the output is recalculated

CodePudding user response:

That's how variables work. When you store something in them it will be how you put it in at the moment. If you want a dynamic result use a function instead:

fun result() = valueA * valueB

and then print like

println(result())

If they are class variables (properties) you actually can use variables but then you need to define it with a getter like this for example:

val result get() = valueA * valueB

CodePudding user response:

If valueA and valueB are in a declaration scope, e.g. in a class/object declaration, you can declare a function or a property with a getter, and compute valueA * valueB, like in Ivo's answer.

If valueA and valueB are in a statement scope, e.g. in a function/lambda's scope (which they look like they are, judging by the fact that you are calling println right after), you cannot declare a property with a getter, but you can still declare functions.

If you don't like the () syntax when calling a function, I offer a third solution - property delegates. This works in both kinds of scopes.

First, make the function type () -> T a property delegate:

operator fun <T> (() -> T).getValue(thisRef: Any?, property: KProperty<*>): T = this()

Then declare result as:

val result by { valueA * valueB }
// then whenever you use "result", it will compute valueA * valueB!

Note that result becomes a val. You cannot change its definition as "valueA times valueB" after this.

Note that this could be breaking the principe of least astonishment. Some might be quite surprised by this.

You also might want to go for something like this instead:

val result by AutomaticComputation { valueA*valueB }

// ...

class AutomaticComputation<T>(val compute: () -> T) {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T = compute()
}

CodePudding user response:

You could always have a bit of fun with Delegates.observable() https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-delegates/observable.html

Example

var valueA by Delegates.observable(0) { _, _, _ ->
    calculateValueC()
}
var valueB by Delegates.observable(0) { _, _, _ ->
    calculateValueC()
}

var valueC: Int = 0

fun calculateValueC() {
    valueC = valueA   valueB
    println(valueC)
}

valueA = 5
valueB = 5

This would produce the output

5
10
  • Related