Kotlin: Apply vs With
Solution 1
There're two differences:
apply
accepts an instance as the receiver whilewith
requires an instance to be passed as an argument. In both cases the instance will becomethis
within a block.apply
returns the receiver andwith
returns a result of the last expression within its block.
I'm not sure there can be some strict rules on which function to choose. Usually you use apply
when you need to do something with an object and return it. And when you need to perform some operations on an object and return some other object you can use either with
or run
. I prefer run
because it's more readable in my opinion but it's a matter of taste.
Solution 2
The apply
function
//returns receiver T, T exposed as `this`
fun <T> T.apply(block: T.() -> Unit): T
Description
The apply
function is invoked on a receiver T
, which will be exposed as this
in the passed lambda expression. The receiver also becomes the result of apply
automatically.
The with
function
//return arbitrary value R, not an extension function, T exposed as `this`
fun <T, R> with(receiver: T, block: T.() -> R): R
Description
The with
function, as opposed to all other scope functions (let
, run
, also
, apply
), is not defined as an extension function. Instead, the function is invoked with a receiver object as its first argument explicitly. Same as apply
, the receiver is exposed as this
in the passed lambda. The result of the lambda, i.e. it’s last statement, becomes the result (R
) of with
.
Solution 3
Here are the Similarities and Differences
Similarities
With and Apply both accept an object as a receiver in whatever manner they are passed.
Differences
With returns the last line in the lambda as the result of the expression.
Apply returns the object that was passed in as the receiver as the result of the lambda expression.
Examples
With
private val ORIENTATIONS = with(SparseIntArray()) {
append(Surface.ROTATION_0, 90)
append(Surface.ROTATION_90, 0)
append(Surface.ROTATION_180, 270)
append(Surface.ROTATION_270, 180)
}
ORIENTATIONS[0] // doesn't work
// Here, using with prevents me from accessing the items in the SparseArray because,
// the last line actually returns nothing
Apply
private val ORIENTATIONS = SparseIntArray().apply {
append(Surface.ROTATION_0, 90)
append(Surface.ROTATION_90, 0)
append(Surface.ROTATION_180, 270)
append(Surface.ROTATION_270, 180)
}
ORIENTATIONS[0] // Works
// Here, using apply, allows me to access the items in the SparseArray because,
// the SparseArray is returned as the result of the expression
Solution 4
"with(here class reference required)" is used for accessing variable of another class but not for method of that class. Now if we want to use variable and method of another class that time we need to use apply(reference.apply{}) Declare a class like below
class Employee {
var name:String = ""
var age:Int = -1
fun customMethod() {
println("I am kotlin developer")
}
}
Now we can access name and age variable of Employee class in onCreate by "with"
val emp = Employee()
with(emp) {
name="Shri Ram"
age=30
}
println(emp.name)
println(emp.age)}
but we cannot access the "customMethod" of Employee class by with
so if we need to use variable along with method, then we need to use "apply":
val emp = Employee()
emp.apply {
name="param"
age=30
}.customMethod()
println(emp.name)
println(emp.age)}
Output of with
I/System.out: Shri Ram
I/System.out: 30
Output of apply
I/System.out: I am kotlin developer
I/System.out: param
I/System.out: 30
Related videos on Youtube
n9Mtq4
Updated on June 19, 2022Comments
-
n9Mtq4 almost 2 years
What is the difference between with and apply. From what I know the following code does the same thing:
swingElement.apply { minWidth = ENABLED_COLUMN_WIDTH maxWidth = ENABLED_COLUMN_WIDTH preferredWidth = ENABLED_COLUMN_WIDTH } with(swingElement) { minWidth = ENABLED_COLUMN_WIDTH maxWidth = ENABLED_COLUMN_WIDTH preferredWidth = ENABLED_COLUMN_WIDTH }
Is there any difference and should I use one over the other? Also, are there some cases where one would work and the other won't?
-
Kirill Rakhman about 8 yearsApply plays better with nullable receivers:
foo?.apply { /* maybe do something */ }
-
Michael about 8 yearsGood point.
run
is not bad too. As for me,with
is absolutely useless. I don't use it in my code. -
Mike Buhot almost 8 yearsif you like to scope your utility methods inside a top level Object, then with can be useful to bring them into scope for a small code block.
-
IgorGanapolsky almost 7 yearsWhat do you mean by receiver? I cannot find its documentation.
-
Michael almost 7 yearsA receiver is an implicit
this
argument for an extension function: kotlinlang.org/docs/reference/extensions.html -
lase about 5 yearsThis really isn't a great example. The last line of
with
returns nothing because you wrote it that way. While it wouldn't be great stylistically, you could putthis
as the last line ofwith
. This is like summing up the differences between a knife and fork by saying "well, the fork isn't very good for cutting". -
Farid almost 4 yearsI'm guessing OP wanted to know use-case differences like a contextual example to choose one over another rather than a description