difference between kotlin also, apply, let, use, takeIf and takeUnless in Kotlin

ぃ、小莉子 提交于 2019-11-27 11:08:23

问题


I read many Kotlin documents about these items. But I can't understand so clearly.

What is the use of Kotlin let, also, takeIf and takeUnless in detail?

I need an example of each item. Please don't post the Kotlin documentation. I need a real-time example and use cases of these items.


回答1:


let

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

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

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

You can use let for null safety check:

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

also

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

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

You can use it for doing 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) return true, else return 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 predicate reversed. If true, return null, else return the receiver.

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

Help

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



回答2:


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

To understand these function you have to understand Extension functions and Lambda functions in Kotlin.

Extension Function:

By the use of extension function, we can create a function for a class without inheriting a class.

Kotlin, similar to C# and Gosu, provides the ability to extend a class with new functionality without having to inherit from the class or use any type of design pattern such as Decorator. This is done via special declarations called extensions. Kotlin supports extension functions and extension properties.

So, to find if only numbers in the String, you can create a method like below without inheriting 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 is prints true.

Lambda Functions:

Lambda functions are just like 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, the block is a lambda function and it is passed as a parameter. You can use the above function like this,

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

The above function will print like this,

Block executed
true

I hope, now you got an idea about Extension functions and Lambda functions. Now we can go to Extension functions one by one.

let

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

Two Types T and R used in the above function.

T.let

T could be any object like String class. so you can invoke this function with any objects.

block: (T) -> R

In parameter of let, you can see the above lambda function. Also, the invoking object is passed as a parameter of the function. So you can use the invoking class object inside the function. then it returns the R (another object).

Example:

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

In above example let takes String as a parameter of its lambda function and it returns Pair in return.

In the same way, other extension function works.

also

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

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

Example:

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

apply

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

Same as also but the same invoking object passed as the function so you can use the functions and other properties without calling it or parameter name.

Example:

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

You can see in the above example the functions of String class directly invoked inside the lambda funtion.

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 above example number will have a string of phoneNumber only it matches the regex. Otherwise, it will be null.

takeUnless

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

It is the reverse of takeIf.

Example:

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

number will have a string of phoneNumber only if not matches the regex. Otherwise, it will be null.



来源:https://stackoverflow.com/questions/45582732/difference-between-kotlin-also-apply-let-use-takeif-and-takeunless-in-kotlin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!