kotlin标准函数|青训营笔记

83 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第14天

标注函数with、run和apply

  • kotlin的标准函数指的是standard.kt文件中定义的函数,任何Kotlin代码都可以自由地调用所有的标准函数
    with 函数
    with 函数接收两个参数:第一个参数可以是一个任意类型的对象,第二个参数则是一个Lambda表达式。with函数会在Lambda表达式中提供第一个参数对象的上下文,并返回Lambda表达式中的最后一行代码
val result = with(obj) { 
 // 这里是obj的上下文 
 "value" // with函数的返回值 
} 

比如在《第一行代码》中演示的那样,有一个水果列表,现在我们想吃完所有水果,并将结果打印出来,就可以这样写:

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) 

仔细观察上述代码,我们发现它连续调用了很多次builder对象的方法。其实这个时候就可以考虑使用with函数来让代码变得更加精简,如下所示:

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape") 
val result = with(StringBuilder()) { 
 append("Start eating fruits.\n") 
 for (fruit in list) { 
 append(fruit).append("\n") 
 } 
 append("Ate all fruits.") 
 toString() 
} 
println(result) 

这段代码乍一看可能有点迷惑性,其实很好理解。首先我们给with函数的第一个参数传入了一 个StringBuilder对象,那么接下来整个Lambda表达式的上下文就会是这个 StringBuilder对象。于是我们在Lambda表达式中就不用再像刚才那样调用 builder.append()和builder.toString()方法了,而是可以直接调用append()和 toString()方法。Lambda表达式的最后一行代码会作为with函数的返回值返回,最终我们 将结果打印出来

run函数

run函数的用法其实和 with函数是非常类似的,只是稍微做了一些语法改动而已。首先run函数通常不会直接调用, 而是要在某个对象的基础上调用;其次run函数只接收一个Lambda参数,并且会在Lambda表 达式中提供调用对象的上下文。其他方面和with函数是一样的。 如上面一个例子

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape") 
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函数
apply函数和run函数也是极其类似的,都要在某 个对象上调用,并且只接收一个Lambda参数,也会在Lambda表达式中提供调用对象的上下 文,但是apply函数无法指定返回值,而是会自动返回调用对象本身。

那么现在我们再使用apply函数来修改一下吃水果的这段代码,如下所示:

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape") 
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()方法才行。