地址
官方解释:
The Kotlin standard library contains several functions whose sole purpose is to execute a block of code within the context of an object. When you call such a function on an object with a lambda expression provided, it forms a temporary scope. In this scope, you can access the object without its name. Such functions are called scope functions
Basically, these functions do the same: execute a block of code on an object. What’s different is how this object becomes available inside the block and what is the result of the whole expression.
大概意思就是kotlin提供这样的语法糖:我们可以在某个对象的“上下文环境”中,创建一个临时的作用域,在这个区域我们可以不显示的调用对象(用it 或者 this),并且当中的变量也是区域性的,共有五个这样的函数,功能相似
那为什么要用呢?很简单,就是增加可读性,更加简洁
先看两个区别:
run、with、apply 使用的context是 this,和其他地方一样,这里的this是可以省略的,但是容易弄混。并且引用的对象是“可见的”,官方参考:
val adam = Person("Adam").apply {
age = 20 // same as this.age = 20 or adam.age = 20
city = "London"
}
print(adam.age) // output 20
与之对应的,剩下的 let、also,将上下文对象作为lambda(即作用域代码块)的参数,如果未指定参数名,则默认名称访问该对象,当然也可以为 上下文对象 自定义名称
(上下文对象就是使用这个方法的对象)
fun getRandomInt(): Int {
return Random.nextInt(100).also {
writeToLog("getRandomInt() generated value $it")
// print("getRandomInt() generated value $it")
}
}
val i = getRandomInt()
// 自定义名称的情况
fun getRandomInt(): Int {
return Random.nextInt(100).also { value ->
writeToLog("getRandomInt() generated value $value")
}
}
apply 和 also 返回值是上下文对象本身,也就是说可以对同一个对象进行链式调用
val numberList = mutableListOf<Double>()
numberList.also { println("Populating the list") }
.apply {
add(2.71)
add(3.14)
add(1.0)
}
.also { println("Sorting the list") }
.sort()
// output
Populating the list
Sorting the list
[1.0, 2.71, 3.14]
let, run,和with返回一个lambda结果
// 官方实例
val numbers = mutableListOf("one", "two", "three")
val countEndsWithE = numbers.run {
add("four")
add("five")
count { it.endsWith("e") }
}
println("There are $countEndsWithE elements that end with e.")
// output
There are 3 elements that end with e.
// 稍微修改下:
val numbers = mutableListOf("one", "two", "three")
val countEndsWithE = numbers.run {
add("four")
add("five")
this.count { it.endsWith("e") }
println("123") // 忽略了返回值 返回有空
// 5 如果最后一行是 ‘5’ 则countEndsWithE 值为5,输出为5
}
println(countEndsWithE)
// output
123
kotlin.Unit
通常用于执行非空,我们可以用他代替if(object != null ){ … },官方例子
// 不用let
val numbers = mutableListOf("one", "two", "three", "four", "five")
val resultList = numbers.map { it.length }.filter { it > 3 }
println(resultList)
// 使用let
val numbers = mutableListOf("one", "two", "three", "four", "five")
numbers.map { it.length }.filter { it > 3 }.let {
println(it)
map.filter{ it > 4}
// and more function calls if needed
}
另一例使用let是在有限的范围内引入局部变量,以提高代码的可读性。若要为上下文对象定义一个新变量,请将其名称作为lambda参数,以便可以使用它而不是默认的it.
fun main() {
val numbers = listOf("one", "two", "three", "four")
val modifiedFirstItem = numbers.first().let { firstItem ->
println("The first item of the list is '$firstItem'")
if (firstItem.length >= 5) firstItem else "!" + firstItem + "!"
}.toUpperCase()
println("First item after modifications: '$modifiedFirstItem'")
}
// output
The first item of the list is 'one'
First item after modifications: '!ONE!'
非扩展函数(A non-extension function),“上下文对象”作为参数传递,可以用“this”,“返回值是lambda的结果”(最后一行的结果),但是官方建议是在“不提供lambda结果的情况下调用上下文对象上的函数”,可以理解为,使用此对象,执行以下操作
val numbers = mutableListOf("one", "two", "three")
with(numbers) {
println("'with' is called with argument $this")
println("It contains $size elements")
}
// output
'with' is called with argument [one, two, three]
It contains 3 elements
也可以用于计算一些值:
fun main() {
val numbers = mutableListOf("one", "two", "three")
val firstAndLast = with(numbers) {
"The first element is ${first()}," +
" the last element is ${last()}"
}
println(firstAndLast)
}
上下文对象可作为接收者(this). 返回值是lambda结果
和with差不多,常用于:同时包含对象初始化和返回值的计算
val service = MultiportService("https://example.kotlinlang.org", 80)
val result = service.run {
port = 8080
query(prepareRequest() + " to port $port")
}
// the same code written with let() function:
val letResult = service.let {
it.port = 8080
it.query(it.prepareRequest() + " to port ${it.port}")
}
上下文对象为this,返回值为本身,主要用于不返回值,并且对自身进行一些配置的情况下
val adam = Person("Adam").apply {
age = 32
city = "London"
}
上下文对象为it ,返回值为本身,使用场景:有关不更改对象的其他操作,如日志记录或打印调试信息
val numbers = mutableListOf("one", "two", "three")
numbers
.also { println("The list elements before adding new one: $it") }
.add("four")
// output
The list elements before adding new one: [one, two, three]
名称 | 对象引用 | 返回值 | 是否为拓展函数 | 使用场景 |
---|---|---|---|---|
let | it | Lambda结果 | 是 | 对非空对象执行(替代 !=) |
run | this | Lambda结果 | 是 | 对象的配置、计算结果 |
run | - | Lambda结果 | 否:在没有上下文对象的情况下调用 | 运行需要表达式的语句 |
with | this | Lambda结果 | 否:接受上下文对象作为参数 | 同一个对象调用多个方法 |
apply | this | 上下文对象 | 是 | 用于对象的配置 |
also | it | 上下文对象 | 是 | 用于一些附加操作 |