When should we use let, also, apply, takeIf, takeUnless in Kotlin

I read a lot of Kotlin documents about these subjects. But I cannot understand so clearly.

What are the benefits of Kotlin let , as well , takeIf and takeUnless ?

I need an example of each element. Please do not post Kotlin documentation. I need a real-time example and use cases of these elements.

+5
source share
2 answers

let it also apply, takeIf, takeUnless are the extension functions in Kotlin.

To understand this function, you must understand in <Boilers. "β†’ Extension functions and Lambda functions .

Extension function:

Using the extension function, we can create a function for the class without inheriting the class.

Kotlin, similar to C # and Gosu, provides the ability to extend a class with new functionality without inheriting from the class or using any type of design, such as Decorator. This is done through special ads called extensions. Kotlin supports extension functions and extension properties.

So, to find only numbers in String , you can create a method like below without inheriting the String class.

 fun String.isNumber(): Boolean = this.matches("[0-9]+".toRegex()) 

you can use the above extension function like this,

 val phoneNumber = "8899665544" println(phoneNumber.isNumber) 

which prints true .

Lambda functions:

Lambda functions are like an interface in Java. But in Kotlin, lambda functions can be passed as a parameter in functions.

Example:

 fun String.isNumber(block: () -> Unit): Boolean { return if (this.matches("[0-9]+".toRegex())) { block() true } else false } 

You can see that the block is a lambda function and is passed as a parameter. You can use the function above, for example,

 val phoneNumber = "8899665544" println(phoneNumber.isNumber { println("Block executed") }) 

The above function will print as follows:

 Block executed true 

I hope you now have an idea about extension functions and Lambda functions. Now we can move on to the Extension functions one by one.

let be

 public inline fun <T, R> T.let(block: (T) -> R): R = block(this) 

The above function uses two types of T and R.

 T.let 

T can be any object, for example, the String class. therefore, you can call this function with any objects.

 block: (T) -> R 

In the let parameter, you can see the lambda function above. In addition, the caller is passed as a parameter to the function. That way you can use the caller of the class inside the function. then it returns R (another object).

Example:

 val phoneNumber = "8899665544" val numberAndCount: Pair<Int, Int> = phoneNumber.let { it.toInt() to it.count() } 

In the above example, let it accept String as a parameter of its lambda function and return Pair in response.

Another extension function works in the same way.

also

 public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this } 

the extension function also takes the calling class as a parameter to the lambda function and returns nothing.

Example:

 val phoneNumber = "8899665544" phoneNumber.also { number -> println(number.contains("8")) println(number.length) } 

To apply

 public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this } 

The same as the same caller, which is passed as a function, so you can use functions and other properties without calling it or the parameter name.

Example:

 val phoneNumber = "8899665544" phoneNumber.apply { println(contains("8")) println(length) } 

In the above example, you can see the functions of the String class directly called inside the lambda function.

takeIf

 public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null 

Example:

 val phoneNumber = "8899665544" val number = phoneNumber.takeIf { it.matches("[0-9]+".toRegex()) } 

In the above example, number will have the string phoneNumber , only it matches regex . Otherwise, it will be null .

takeUnless

 public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? = if (!predicate(this)) this else null 

This is the opposite of takeIf.

Example:

 val phoneNumber = "8899665544" val number = phoneNumber.takeIf { it.matches("[0-9]+".toRegex()) } 

number will have the string phoneNumber if regex does not match. Otherwise, it will be null .

+2
source

let be

public inline fun <T, R> T.let(block: (T) -> R): R = block(this)

Take the receiver and pass it to the function passed as a parameter. Return the result of the function.

 val myVar = "hello!" myVar.let { println(it) } // Output "hello!" 

You can use let to verify security:

 val myVar = if (Random().nextBoolean()) "hello!" else null myVar?.let { println(it) } // Output "hello!" only if myVar is not null 

and

public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }

Execute the function passed with the receiver as a parameter and return the receiver.
It's like let, but it always returns the receiver, not the result of the function.

You can use it to do something on an object.

 val person = Person().also { println("Person ${it.name} initialized!") // Do what you want here... } 

takeIf

public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null

Return the receiver if the function (predicate) returns true, else returns null.

 println(myVar.takeIf { it is Person } ?: "Not a person!") 

takeUnless

public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? = if (!predicate(this)) this else null

Same as takeIf , but with a change in the predicate. If true, return null, else return the receiver.

 println(myVar.takeUnless { it is Person } ?: "It a person!") 

reference

  • You can easily use https://try.kotlinlang.org/ for testing. You can find examples here .
  • You can check the source of the standard lib here . let , also , takeIf and takeUnless here .
+14
source

Source: https://habr.com/ru/post/1270706/


All Articles