一文理解 kotlin 中的run、with、apply、also、let的区别
在使用 kotlin 开发中,我们常常会使用到 let、 run、 with、 apply、 以及 also这五个函数。它们的作用就是在对象的上下文中执行代码块。在 Kotlin 中,这五个函数都可以在代码块的作用域中访问对象而无需其名称,因此它们被称为这五个函数主要的应用场景如下图所示,图片来源可以看到这些函数基本上都执行同样的操作,即在一个对象上执行一个代码块。。
在使用 kotlin 开发中,我们常常会使用到 let、 run、 with、 apply、 以及 also 这五个函数。它们的作用就是在对象的上下文中执行代码块。
在 Kotlin 中,这五个函数都可以在代码块的作用域中访问对象而无需其名称,因此它们被称为作用域函数
这五个函数主要的应用场景如下图所示,图片来源Google 工程师的推特帖子

可以看到这些函数基本上都执行同样的操作,即在一个对象上执行一个代码块。不同的是这个对象在代码块中如何使用,以及整个表达式的结果是什么。 。下面就详细介绍一下它们的区别:
函数原型上的区别
如果我们从函数原因上来看这五个作用域函数,可以讲它们分成三种,分别是:
- 函数原型为扩展函数,这一类有
let、apply、also - 函数原型不是扩展函数,这一类有
with - 以及既有扩展函数实现方式也有非扩展函数实现方式的
run
对于函数原型为扩展函数的 let、apply、also 来说,它们必须需要一个对象才能调用,代码如下:
kotlin
代码解读
复制代码
Person("Adam").apply {
age = 20
city = "London"
}
而对于函数原型非扩展函数的 with 来说,它可以直接被调用,代码示例如下:
kotlin
代码解读
复制代码
val numbers = mutableListOf("one", "two", "three")
with(numbers) {
val firstItem = first()
val lastItem = last()
println("First item: $firstItem, last item: $lastItem")
}
而对于 run,由于它有两种实现,因此上面两种方式都可以调用。
引用上下文对象的方式
run、with 以及 apply 通过关键字 this 来引用上下文对象的。 而 let 及 also 则是通过 it(默认情况下)来访问上下文对象的。最主要的区别是,在访问对象自身的属性时,this 可以省略,而 it 不可以,代码相对来说比较简洁。代码示例如下:
kotlin
代码解读
复制代码
Person("Adam").apply {
age = 20 // 等同于 this.age = 20
city = "London"
}
但是当上下文对象主要用作函数调用中的参数时,通过 it 访问上下文对象会更好。 在代码块中使用多个变量时,it 也更好一些。代码示例如下:
kotlin
代码解读
复制代码
fun getRandomInt(): Int {
return Random.nextInt(100).also {
writeToLog("getRandomInt() generated value $it")
}
}
返回值的区别
根据返回结果的不同,五个作用域函数可以分为以下两类:
apply及also:返回上下文对象自己let、run及with:返回代码块的结果
代码示例如下:
kotlin
代码解读
复制代码
fun getRandomInt(): Int {
// 返回 int 自己
return Random.nextInt(100).also {
writeToLog("getRandomInt() generated value $it")
}
}
val numbers = mutableListOf("one", "two", "three")
// 返回代码块的结果
val countEndsWithE = numbers.run {
add("four")
add("five")
count { it.endsWith("e") }
}
小结
上文介绍了五个作用域函数在函数应用场景、函数原型、函数上下文对象、函数返回值这几个方面来比较上述作用域函数的不同点。五个作用域函数的不同点如下表所示:
| 函数 | 对象引用 | 返回值 | 是否是扩展函数 |
|---|---|---|---|
let |
it |
Lambda 表达式结果 | 是 |
T.run{ } |
this |
Lambda 表达式结果 | 是 |
run{ } |
- | Lambda 表达式结果 | 不是:调用无需上下文对象 |
with |
this |
Lambda 表达式结果 | 不是:把上下文对象当做参数 |
apply |
this |
上下文对象 | 是 |
also |
it |
上下文对象 | 是 |
参考
- Kotlin Standard Functions cheat-sheet | by Jose Alcérreca | Android Developers | Medium
- 作用域函数 · Kotlin 官方文档 中文版 (kotlincn.net)
作者:小墙程序员
链接:https://juejin.cn/post/7381657886802067456
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
更多推荐



所有评论(0)