kotlin中let、run、apply的区别
Kotlin 中的 let、run 和 apply 都是 Scope Functions(<font color='red'>作用域函数</font>),用于限定一个代码块的作用域。它们的区别在于返回值和使用场景上。
一. 语法
1. let 函数:
源码:
// 参数 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 函数适合对一个对象进行一系列处理,并返回处理结果的场景。
2. run 函数:
源码:
// 参数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 表达式的参数作为返回值。
3. apply 函数:
源码:
// 返回的是对象自己
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 函数适合对一个对象进行一系列操作,例如初始化对象的属性,而不需要返回结果的场景。因为它返回的是对象本身,所以可以使用链式调用。
二. 使用场景
1. let 的使用场景
假设有一个字符串,我们想要将它转换成大写并打印出来,可以使用 let 函数来实现:
val str = "hello world"
str.let {
it.toUpperCase()
}.let {
println(it)
}
在这个例子中,我们首先调用了 let 函数,并将字符串 str 作为参数传入,然后在 lambda 表达式内部调用了 toUpperCase() 方法将字符串转换成大写,并将结果返回。由于 let 函数的返回值就是 lambda 表达式的执行结果,所以我们可以继续链式调用另一个 let 函数,并在其内部打印出转换后的字符串。
2. run 的使用场景
假设有一个可空的字符串,我们想要在它不为空的情况下将它转换成大写并打印出来,可以使用 run 函数来实现:
val str: String? = "hello world"
str?.run {
toUpperCase()
}.run {
println(this)
}
在这个例子中,我们首先通过安全调用运算符 ?. 判断字符串是否为空,如果不为空则将其作为 lambda 表达式的接收者,调用 toUpperCase() 方法将字符串转换成大写,并返回结果。由于 run 函数将 lambda 表达式的执行结果作为返回值,所以我们可以继续链式调用另一个 run 函数,并在其内部打印出转换后的字符串。
3. apply 的使用场景
假设有一个 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 并直接使用它。