kotlin also, apply, let, use, takeIf 和 takeUnless 在 Kotlin 中的区别

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

我阅读了很多关于这些项目的 Kotlin 文档。但是我理解的不是很清楚。

Kotlin有什么用 let, also, takeIf and takeUnless详细?

我需要每个项目的示例。请不要 post Kotlin 文档。我需要这些项目的实时示例和用例。

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

获取接收器并将其传递给作为参数传递的函数。 Return 函数的结果。

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

您可以使用 let 进行空安全检查:

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

还有

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

执行以 receiver 作为参数和 return receiver.
传递的函数 就像 let 但总是 return 接收者 ,而不是函数的结果。

您可以使用它对对象进行操作。

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 receiver if the function (predicate) return true, else return null.

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

取除非

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

takeIf 相同,但谓词相反。如果为真,return 为空,否则 return 接收者 .

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

帮助

let, also, apply, takeIf, takeUnless 是 Kotlin 中的扩展函数。

要了解这些函数,您必须了解 Kotlin 中的扩展函数Lambda 函数

扩展函数:

通过使用扩展函数,我们可以在不继承class的情况下为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.

所以,如果只查找 String 中的数字,您可以创建如下所示的方法而不继承 String class.

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

可以这样使用上面的扩展函数,

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

这是打印 true.

Lambda 函数:

Lambda函数就像Java中的接口(只包含一个方法。也称为单一抽象方法)。从 Java 开始,java 中也提供了 8 个 lambda。在 Kotlin 中,lambda 无处不在。大多数 lambda 表达式作为函数中的参数传递。

示例:

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

您可以看到,该块是一个 lambda 函数,它作为参数传递。你可以像这样使用上面的函数,

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

上面的函数会这样打印,

Block executed

希望您现在对扩展函数和 Lambda 函数有所了解。现在我们可以一一进入扩展功能了。

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

上述函数中使用了两种类型 T 和 R。

T.let

T 可以是任何对象,如字符串、数字或任何类型。所以你可以用任何对象调用这个函数。

block: (T) -> R

你可以看到 lambda 函数在 let 的参数中将调用对象作为函数的参数传递。所以你可以在函数内部使用调用 class 对象。然后它 return 是 R(另一个对象)。

示例:

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

在上面的例子中,let 将 String 作为其 lambda 函数的参数,它 returns Pair in return.

其他扩展功能同理

还有

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

扩展函数 also 将调用 class 作为 lambda 函数参数,return 什么都没有。

示例:

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

申请

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

与函数相同,但传递的调用对象与函数相同,因此您可以使用函数和其他属性而无需调用它或参数名称。

示例:

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

你可以在上面的例子中看到在 lambda 函数中直接调用了 String class 的函数。

takeIf

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

示例:

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

在上面的例子中 number 将有一个字符串 phoneNumber 只有它匹配 regex。否则,它将是 null.

取除非

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

与takeIf相反

示例:

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

number 只有在不匹配 regex 时才会有一个 phoneNumber 的字符串。否则,它将是 null.