Kotlin: What is the difference between Apply and Also
Short answer: also
was introduced for semantic reasons.
Long answer:
If you use apply
you always refer to the receiver with this
.
val person = Person().apply {
name = "Tony Stark" // this. can be omitted
age = 52 // this. can be omitted
// ...
}
This way you don't have to repeat person several times as shown here:
person.name = "Tony Stark"
person.age = 52
If the block becomes longer you may want to give this
a name. That's why also
was introduced. Now you can refer to the receiver either by it
or an explicit name. This is especially useful if you want to use another name than (in this case person
) before:
val person = Person().also { newPerson ->
newPerson.name = "Tony Stark"
newPerson.age = 52
// ...
}
So, depending on how well you code should be readable you can always use one or the other.
TL;DR Difference
The also
function takes a lambda in which you refer to the object you called the function on (receiver T
) with either it
(implicit name) or a custom name.
val person = Person().also {
it.name = "Tony Stark"
}
With apply
, on the other hand, a function literal with receiver is used so inside the passed in lambda you can access the receiver’s members directly, as you see in the following. The receiver can be referenced by this
.
val person = Person().apply {
name = "Tony Stark"
}
also
Declaration:
inline fun <T> T.also(block: (T) -> Unit): T (source)
Calls the specified function block with this
(the receiver) value as its argument and returns this
(the receiver) value.
apply
Declaration:
inline fun <T> T.apply(block: T.() -> Unit): T (source)
Calls the specified function block with this
value as its receiver and returns this
(the receiver) value.
when to use what
Usage examples are explained in this thread.
- Both function returns receiver object itself.
- They differ in accessing the receiver object.
It is your decision which one to use. However, in Kotlinlang's website https://kotlinlang.org/docs/reference/scope-functions.html, there is a convention for their usage
Use also for additional actions that don't alter the object, such as logging or printing debug information.
val numbers = mutableListOf("one", "two", "three")
numbers
.also { println("The list elements before adding new one: $it") }
.add("four")
The common case for apply is the object configuration.
val adam = Person("Adam").apply {
age = 32
city = "London"
}
println(adam)