let
let既不是操作符,也不是什么关键字,而是一个函数。
这个函数提供了函数式API的编程接口,并将原始调用对象作为参数传递到 Lambda 表达式中。
obj.let { obj2 ->
// 编写具体的业务逻辑
}
这里调用了obj对象的let函数,然后Lambda 表达式中的代码就会立即执行,并且 这个obj对象本身还会作为参数传递到Lambda 表达式中。不过,为了防止变量重名,这里我将 参数名改成了obj2,但实际上它们是同一个对象。
with、run、apply
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
val builder = StringBuilder()
builder.append("Start eating fruits.\n")
for (fruit in list) {
builder.append(fruit).append("\n")
}
builder.append("Ate all fruits.")
val result = builder.toString()
println(result)
/*
with函数接收两个参数:第一个参数可以是一个任意类型的对象,第二个参数是一个Lambda 表达式。
with函数会在Lambda 表达式中提供第一个参数对象的上下文,并使用Lambda 表达式中的最后一行代码作为返回值返回。
val result = with(obj) {
// 这里是obj的上下文
...
"value" // with函数的返回值
}
*/
val result = with(StringBuilder()) {
append("Start eating fruits.\n")
for (fruit in list) {
append(fruit).append("\n")
}
append("Ate all fruits.")
toString()
}
/*
首先,run函数通常不会直接调用,而是要在某个对象的基础上调用;
其次,run函数只接收一个Lambda 参数,并且会在Lambda 表达式中提供调用对象的上下文。
其他方面和with函数是一样的,包括也会使用Lambda 表达式中的最后一行代码作为返回值返回。
val result = obj.run {
// 这里是obj的上下文
...
"value" // run函数的返回值
}
*/
val result = StringBuilder().run {
append("Start eating fruits.\n")
for (fruit in list) {
append(fruit).append("\n")
}
append("Ate all fruits.")
toString()
}
println(result)
/*
apply函数和run函数也是极其类似的,都要在某个对象上调用,并且只接收一个Lambda 参数,也会在Lambda 表达式中提供调用对象的上下文。
但是,apply函数无法指定返回值,而是会自动返回 **调用对象** 本身。
val result = obj.apply {
// 这里是obj的上下文
}
// result == obj
*/
val result = StringBuilder().apply {
append("Start eating fruits.\n")
for (fruit in list) {
append(fruit).append("\n")
}
append("Ate all fruits.")
}
println(result.toString())
由于apply函数无法指定返回值,只能返回调用对象本身,因此这里的 result实际上是一个StringBuilder对象,所以我们在最后打印的时候还要再调用它的 toString()方法才行。