Kotlin Scope Functions
Scope functions is one of the Kotlin feature I really like. When using such a function on an object, you are executing a block of code within the context of that object. You won’t find a similar feature in Java. There are five scope functions available in Kotlin: let
, apply
, run
, with
and also
. In fact all of them is doing the same thing – execute a block of code on an object. However, there are some differences and we will discuss them on the simple example of code.
Example
The source code repository used for this article is available on my GitHub in repository sample-kotlin-playground. It is available here: https://github.com/piomin/sample-kotlin-playground.git.
Apply scope function
Apply refer to the context object as a lambda receiver – by keyword this
. It is the same as “you would be inside” the class of that object. You can even omit the keyword this
. As a results it just returns the context object. All these features makes it ideal for changing value of object fields. Let’s take a look on the following example of code. Then we will try to implement the same functionality using other scope function.
@Test fun testApplyFunction() {
val p: Person = Person("John", "Smith", 1)
.apply {
age = 20
localization = "London"
}
Assert.assertEquals(20, p.age)
Assert.assertEquals("London", p.localization)
}
Let
Let is able to access the context object as a lambda argument. If the argument name is not specified, the object is accessed by the implicit default name it
. It is returning the lambda result. What means that if we want to do the same thing with person object as in the previous sample we need to return exactly that object.
@Test fun testLetFunction() {
val p: Person = Person("John", "Smith", 1)
.let {
it.age = 20
it.localization = "London"
it
}
Assert.assertEquals(20, p.age)
Assert.assertEquals("London", p.localization)
}
Run scope function
Run the same as apply
function refers to the context object as a lambda receiver. But unlike apply
it returns the lambda result instead of the context object. The test is very similar to the testApplyFunction
– the only difference is that we have to return object using this
keyword.
@Test fun testRunFunction() {
val p: Person = Person("John", "Smith", 1)
.run {
age = 20
localization = "London"
this
}
Assert.assertEquals(20, p.age)
Assert.assertEquals("London", p.localization)
}
Also scope function
We can use also function to do some additional work after previous changes. Let’s implement our test with apply
in slightly different way. Function also
returns the context object and takes the context object as a lambda argument.
@Test fun testAlsoFunction() {
val p: Person = Person("John", "Smith", 1)
.apply {
age = 20
localization = "London"
}
.also {
Assert.assertEquals(20, it.age)
Assert.assertEquals("London", it.localization)
}
}
TakeIf scope function
TakeIf is not a scope function. It is in addition provided by the Kotlin standard library together with takeUnless
. While takeIf
returns this object if it matches the predicate, takeUnless
returns the object if it doesn’t match the predicate and null if it does. Let’s take a look on the simple test that illustrates usage of this function.
@Test fun testTakeIfFunction() {
var p: Person? = Person("John", "Smith", 1).takeIf { it.id > 1 }
Assert.assertNull(p)
p = Person("John", "Smith", 1).takeIf { it.id == 1 }
Assert.assertNotNull(p)
}
4 COMMENTS