This topic is highly underrated so it's good to know why we should try to use immutable properties.
I would like to point some safety measures when it comes to writing in Kotlin. Kotlin has awesome API's that allows us to write clean, safe and readable code.
One of safety guns in Kotlin is defining immutable properties val or read-write properties var
val num = 10
num = 5 //this is not allowed
The properties in Kotlin are encapsulated by default. That means that even num is read-only property, it can have custom getter or it can hold mutable object like mutableListOf()
which you can operate on.
val list = mutableListOf(2,3,4)
list.add(5) //this gives us more flexibility
or even we can specify custom getter:
class Rectangle(val width: Int, val height: Int) {
val area: Int
get() = this.width * this.height
}
With above examples we've seen that Kotlin is protecting us by default if we use val property.
The big question is, why we should use it in our classes which holds state?
Let's see this example:
var num = 0
for(i in 0..1000) {
thread {
Thread.sleep(10)
num++
}
}
Thread.sleep(3000)
println(num)
In example above there are high chances that num will not be 1000 because some threads will change value of this property and we will not have consistent app after all.
The same applies with coroutines. The value will be modified as well.
Limiting mutability in Kotlin:
- val keyword (we can make custom getter or use delegation)
- copy keyword applied on data class objects
- mutable collections (
mutableMapOf()
mutableListOf()
...etc)
Prefer object and classes that are immutable over mutable. But if you need to change them, consider making immutable data classes and use a copy to change the state.
data class User(
val name: String,
val surname: String,
val address: String
)
Let's say that user has changed his address in the meantime so we want to change this immutable adress property with copy.
val johny = User(
"John",
"Johnny",
"Beverly Hills 74"
)
val johnyWithNewAdress = johny.copy(adress = "Holywood 12")
Another big mistake when it comes to mutability is down-casting immutable collection. This is huge mistake and please don't do it.
Example:
val list = listOf(1,2,3,4,6)
if (list is MutableList) {
list.add(5) //DON'T DO THIS
}
//Do THIS INSTEAD
val list = listOf(1,2,3,4,6)
val newList = list.toMutableList()
newList.add(5)
Here our list is not modified by outside, instead it creates copy of new list which you can easily modify.
There are some exception to this rules but chose it wisely, sometimes we need object to be fully mutable. Baseline is that we should limit mutability as much as possible.
Top comments (0)