Kotlin: What is the difference between Apply and Also

Solution 1:

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.

Solution 2:

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.

Solution 3:

  • Both function returns receiver object itself.
  • They differ in accessing the receiver object.

enter image description here

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)