Kotlin 中的 let
、run
和 apply
都是 Scope Functions(作用域函数),用于限定一个代码块的作用域。它们的区别在于返回值和使用场景上。
源码:
// 参数 block: (T) -> R 普通的函数类型
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
语法:
object.let {
// 在此处使用 object
}
let
函数是将一个对象作为 lambda 表达式的参数,在 lambda 表达式内部可以通过 it
引用这个对象。它的返回值是 lambda 表达式的执行结果。
let
函数适合对一个对象进行一系列处理,并返回处理结果的场景。
源码:
// 参数block: T.() -> R 是一个带有接收者的函数类型
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
语法:
object.run {
// 在此处使用 object
}
run
函数是将一个对象作为 lambda 表达式的接收者,在 lambda 表达式内部可以通过 this
或省略掉 this
直接访问对象的方法和属性。它的返回值是 lambda 表达式的执行结果。
run
函数适合对一个对象进行一系列处理,并返回处理结果的场景。它和 let
函数的不同在于,run
函数将 lambda 表达式的执行结果作为返回值,而 let
函数将 lambda 表达式的参数作为返回值。
源码:
// 返回的是对象自己
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
语法:
object.apply {
// 在此处使用 object
}
apply
函数是将一个对象作为 lambda 表达式的接收者,在 lambda 表达式内部可以通过 this
或省略掉 this
直接访问对象的方法和属性。它的返回值是对象本身。
apply
函数适合对一个对象进行一系列操作,例如初始化对象的属性,而不需要返回结果的场景。因为它返回的是对象本身,所以可以使用链式调用。
假设有一个字符串,我们想要将它转换成大写并打印出来,可以使用 let
函数来实现:
val str = "hello world"
str.let {
it.toUpperCase()
}.let {
println(it)
}
在这个例子中,我们首先调用了 let
函数,并将字符串 str
作为参数传入,然后在 lambda 表达式内部调用了 toUpperCase()
方法将字符串转换成大写,并将结果返回。由于 let
函数的返回值就是 lambda 表达式的执行结果,所以我们可以继续链式调用另一个 let
函数,并在其内部打印出转换后的字符串。
假设有一个可空的字符串,我们想要在它不为空的情况下将它转换成大写并打印出来,可以使用 run
函数来实现:
val str: String? = "hello world"
str?.run {
toUpperCase()
}.run {
println(this)
}
在这个例子中,我们首先通过安全调用运算符 ?.
判断字符串是否为空,如果不为空则将其作为 lambda 表达式的接收者,调用 toUpperCase()
方法将字符串转换成大写,并返回结果。由于 run
函数将 lambda 表达式的执行结果作为返回值,所以我们可以继续链式调用另一个 run
函数,并在其内部打印出转换后的字符串。
假设有一个 Person
类,我们想要创建一个实例并初始化它的属性,可以使用 apply
函数来实现:
data class Person(var name: String, var age: Int)
val person = Person("", 0).apply {
name = "Tom"
age = 18
}
在这个例子中,我们首先调用了 apply
函数,并将一个空的 Person
实例作为参数传入,然后在 lambda 表达式内部对其属性进行初始化,最后返回初始化后的 Person
实例。由于 apply
函数的返回值就是对象本身,所以我们可以将其赋值给一个变量 person
并直接使用它。