kotlin作用域函数

  • kotlin作用域函数

  • 资料来源:

    https://www.kotlincn.net/docs/reference/scope-functions.html

  • 更新

    1
    20.06.20 初始化

导语

习惯了一堆的 ?.let{...},.apply{...},没想到还有专门的名称.特此记录.

作用域函数

作用域函数是 kt 标准库的几个函数,在对象后面跟着一个 lambda,在 lambda 内可以无需对象名就能访问对象.根据不同的情况使用作用域函数,可以提高代码的可读性.

主要有 let, run, with, apply, also 五个.它们的区别是 lambda 内引用对象的方式是 this 还是 it.还有就是执行结束后返回的类型.

  • this: run, with, apply.实际上也可以省略 this 直接写成员变量和方法.

  • it: let, also.it 代表对象有更好的可读性,当然你可以显式声明对象名.

  • apply, also.执行结束后返回对象本身,这意味着可以在 lambda 做一些初始化的工作.

  • let, run, with.返回 lambda 的结果,通常配合其他 kt 语法,简化代码.

let

lambda 内访问对象是 it,执行完毕返回 lambda 的执行结果.

使用

  • 最常见的是配合 ?. 确保非空调用.
  • 当需要定义一个新变量而这个变量作用域有限时,可以使用 let 简化代码.

示例

1
2
3
4
5
6
7
8
9
10
val length = str?.let {
println("let() called on $it")
processNonNullString(it)
it.length
}

val modifiedFirstItem = numbers.first().let { firstItem ->
println("The first item of the list is '$firstItem'")
if (firstItem.length >= 5) firstItem else "!" + firstItem + "!"
}.toUpperCase()

with

lambda 内访问对象是 this,执行完毕返回 lambda 执行结果.

使用: 大意是 得到了这个对象,然后执行一些操作,与 let 类似.

  • 一些需要执行对象内部函数的过程可以使用 with 简化代码,this 简化不写.

使用

1
2
3
4
5
val numbers = mutableListOf("one", "two", "three")
val firstAndLast = with(numbers) {
"The first element is ${first()}," +
" the last element is ${last()}"
}

run

lambda 内访问对象是 this,执行完毕返回 lambda 执行结果.

使用

  • 与 with 干的事情相同,仅调用方式不同
  • 当需要在 lambda 表达式同时进行对象初始化和返回值的计算时.

示例

1
2
3
4
val result = service.run {
port = 8080
query(prepareRequest() + " to port $port")
}

apply

lambda 内访问对象是 this,执行完毕返回对象自身.

使用

  • 无需多言,需要对对象进行链式操作时候.
  • 配合 return 可以对返回的对象进行一些操作.

示例

1
2
3
4
5
val adam = Person("Adam").apply {
age = 32
city = "London"
}
println(adam)

also

lambda 内访问对象是 it,执行完毕返回对象自身.

takeIf/takeUnless

这个倒是最近看到的,takeIf/takeUnless 可以看作是单个对象的过滤器,相当于 if + lambda 的条件.

  • takeIf: 当 lambda 结果为 true,返回对象自身,否则返回 null.
  • takeUnless: 相反,lambda 为 true 返回 null,为 false 返回对象自身.
  • 配合作用域函数,就不说了,主要是 let.
1
2
3
4
5
6
fun displaySubstringPosition(input: String, sub: String) {
input.indexOf(sub).takeIf { it >= 0 }?.let {
println("The substring $sub is found in $input.")
println("Its start position is $it.")
}
}