Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin val difference getter override vs assignment

Tags:

getter

kotlin

I started playing arround with Kotlin and read something about mutable val with custom getter. As refered in e.g here or in the Kotlin Coding Convention one should not override the getter if the result can change.

class SampleArray(val size: Int) {
    val isEmpty get() = size == 0  // size is set at the beginning and does not change so this is ok
}

class SampleArray(var size: Int) {
    fun isEmpty() { return size == 0 }  // size is set at the beginning but can also change over time so function is prefered
}

But just from the perspective of usage as in the guidelines where is the difference between the following two

class SampleArray(val size: Int) {
    val isEmpty get() = size == 0  // size can not change so this can be used instad of function
    val isEmpty = size == 0        // isEmpty is assigned at the beginning ad will keep this value also if size could change
}

From this answer I could see that for getter override the value is not stored. Is there something else where the getter override is different form the assignment? Maybe with delegates or latinit?

like image 893
FreshD Avatar asked Aug 01 '17 09:08

FreshD


People also ask

What Val means in Kotlin?

Kotlin uses two different keywords to declare variables: val and var . Use val for a variable whose value never changes. You can't reassign a value to a variable that was declared using val . Use var for a variable whose value can change.

How does kotlin change Val value?

VAL(Value)The object stored using val cannot be changed, it cannot be reassigned, it is just like the final keyword in java. val is immutable. Once assigned the val becomes read-only, however, the properties of a val object could be changed, but the object itself is read-only.


2 Answers

The key difference here is that in val isEmpty get() = ... the body is evaluated each time the property is accessed, and in val isEmpty = ... the expression on the right hand side gets evaluated during the object construction, the result is stored in the backing field and this exact result is returned each time the property is used.

So, the first approach is suitable when you want the result to be calculated each time, while the second approach is good when you want the result to be calculated only once and stored.

like image 184
hotkey Avatar answered Oct 18 '22 22:10

hotkey


In your second example size is immutable value and therefore both ways are valid.

However variant with overridden getter get() = size == 0 has no backing field and therefore size == 0 is evaluated every time you access isEmpty variable.

On the other hand, when using initializer = size == 0 the expression size == 0 is evaluated during construction (check exactly when and how here - An in-depth look at Kotlin’s initializers) and stored to the backing field, of which value is then returned when you access the variable.

like image 21
Bojan P. Avatar answered Oct 19 '22 00:10

Bojan P.