问题
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
andtakeUnless
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