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