引言
在kotlin中第一句话 : 函数是第一公民,一切皆函数。
偶然间:看到一个名词作用域函数。字面意思: 在一个作用域内执行的函数。
查了资料看看概念:
Kotlin 标准库包含几个函数,它们的唯一目的是在对象的上下文中执行代码块。
当对一个对象调用这样的函数并提供一个lambda表达式
时,它会形成一个临时作用域。在此作用域中,可以访问该对象而无需其名称。这些函数称为作用域函数。
共有以下五种:let
、run
、with
、apply
以及also
。
结论:
函数 | 对象引用 | 返回值 | 是否是扩展函数 |
---|---|---|---|
let | it | Lambda表达式结果 | 是 |
run | this | Lambda表达式结果 | 是 |
run | - | Lambda表达式结果 | 不是:调用无需上下文对象 |
with | this | Lambda表达式结果 | 不是:把上下文对象当做参数 |
apply | this | 上下文对象 | 是 |
also | it | 上下文对象 | 是 |
用法:
- 对一个非空(non-null)对象执行 lambda 表达式:let
- 将表达式作为变量引入为局部作用域中:let
- 对象配置:apply
- 对象配置并且计算结果:run
- 在需要表达式的地方运行语句:非扩展的 run
- 附加效果:also
- 一个对象的一组函数调用:with 不同作用域函数的使用场景存在重叠,可以根据项目或团队中使用的特定约定来选择使用哪些函数。
虽然作用域函数可以让代码更加简洁,但是要避免过度使用它们:这会使代码难以阅读并可能导致错误。
建议避免嵌套作用域函数,同时链式调用它们时要小心:因为很容易混淆当前上下文对象与this
或it
的值。
also
函数声明
public inline fun <T> T.also(block: (T) -> Unit): T
also
函数是对泛型 T 的扩展函数,接收一个参数类型为T、无返回值(返回值为Unit类型)的函数,且also
函数的返回值就是调用者。
对于执行一些将上下文对象作为参数的操作很有用。
代码中看到 also 时,可以将其理解为并且用该对象执行以下操作。
例子:
val alsoResult = book.also {
it.changePrice(20)
it.name = "alsoResult"
}
println("alsoResult $alsoResult")
结果: alsoResult Book(name=alsoResult, price=20)
apply
函数声明
public inline fun <T> T.apply(block: T.() -> Unit): T
apply
是泛型 T 的扩展函数,接收一个带有 T 类型接收者的无参、无返回值的函数,并且apply
函数返回值就是 T 类型,也就是调用者的类型。
apply最常见的使用场景是用于对象配置。apply可以理解为将以下赋值操作应用于对象。
val applyResult = book.apply {
changePrice(200)
name = "applyResult"
}
println("applyResult $applyResult")
结果:applyResult Book(name=applyResult, price=200)
.
let
函数声明
public inline fun <T, R> T.let(block: (T) -> R): R
let 是对泛型 T 的扩展函数,该扩展函数接收一个函数参数,并且函数参数的接收一个 T 类型的参数,且返回值是 R 类型,也是let
这个扩展函数的返回值类型。
- let 可用于在调用链的结果上调用一个或多个函数。
- let 经常用于执行包含非空值代码块。如需对非空对象执行操作, 可对其使用安全调用操作符
?.
并调用 let 在 lambda 表达式中执行操作。
run
函数声明
public inline fun <T, R> T.run(block: T.() -> R): R
public inline fun <R> run(block: () -> R): R
第一种,看起来就是把let
中函数参数中的 T 类型参数改成了接收者类型,也是返回 R 类型;这和apply
与also
的区别是一样的。
with
函数声明
public inline fun <T, R> with(receiver: T, block: T.() -> R): R
with
并不是扩展函数,需要传入一个T 类型的receiver,可以在 block 中访问这个receiver的方法和属性.
- 上下文对象作为接收者(this)使用。
- 返回值是 lambda 表达式结果。
建议当不需要使用 lambda 表达式结果时,使用 with 来调用上下文对象上的函数。
with 可以理解为对于这个对象,执行以下操作.
val withResult = with(book) {
changePrice(300)
name = "withResult"
this //作为返回值
}
println("withResult $withResult")
结果:withResult Book(name=withResult, price=300)
结束。