Kotlin 作用域函数 [Scope Function](下)
前言
上一篇文章介绍过 Kotlin 中作用域函数,并以函数run
为例,介绍作用域函数的特点和使用。除run
之外,Kotlin 标准库还内置了let
,apply
,also
等几个常用作用域函数,下面介绍它们用法和使用场景。
概览
1. 常见作用域函数模板化结构
run
,let
,apply
,also
,4 个作用域函数,其实是 2 个特性的组合结果:
调用作用域函数的对象,是作为
this
传入,还是作为唯一参数(默认为it
)传入;作用域函数的返回值,是调用的对象,还是 lambda 的返回值。
用伪代码来解释一下:
xxx
可以是run
,let
,apply
,also
其中一个。
如果xxx = run/let
,那么 result == lambdaResult
;而如果xxx = apply/also
,那么 result == object
。且lambdaResult
这一行会报错,因为apply
,also
的 lambda 返回值必须是 Unit。
lambda 最后一行的值会作为 lambda 的返回值。它等价于
return@xxx lambdaResult
。@xxx
表示返回的是这个 lambda,而不是退出整个上层方法。
如果xxx = let/also
,那么param == object
;而如果xxx = run/apply
的话,那么 lambda 是个无参数 lambda,不存在param
, param ->
会报错;
如果 lambda 为单参数 lambda,此时
param ->
可以省略,Kotlin 提供默认的单参数名it
总结成表就是:
快速记忆:4 个常用作用域函数分别是 2 个特性的两两组合,不需要专门记忆。
2. run/let/apply/also 使用场景举例
已经知道这 4 个作用域函数的特点,那么怎么用好它们呢?下面一起来看下这几个作用域函数的使用场景。
2.1 run 函数
这是项目中的一段代码:
run
方法很适合用在对某个对象做一系列操作。可空对象mRecordViewHelper
使用run
方法转换成非空对象this
传入到 lambda 中,并在 lambda 内部进行一系列的赋值和方法调用。run
的返回值是 lambda 的最后一行结果,在这个示例是Unit
。使用 lambda 结果的用例较少,主要就是这种转换为this
的用法。
2.2 let 函数
使用run
还是使用let
更像是编码习惯问题,因为有些人不习惯把调用对象转换成this
,而更喜欢用入参it
。
使用run
还是使用let
的确没有太大区别。不过这几种情况,更建议使用let
:
调用对象主要作为参数,而不是用于初始化或方法调用时。
当 lambda 中需要用到类的
this
时;
总结一下:
当 lambda 主要执行的是调用对象的方法和赋值时,建议使用
run
;而当调用对象主要用作参数时,建议使用
let
;当 lambda 会用到类的
this
时,建议使用let
。
2.3 apply 函数
apply
和run
的区别主要在于,apply
返回的是调用对象。这个特性使得apply
很适合用来做初始化的工作。如:
apply
很适合用来做 property 的初始化,这样 property 的初始化代码就不用写在 init 块里,做到了代码的高内聚。
2.4 also 函数
also 的适用场景,和run
与let
差不多,是与apply
来做对比的。具体建议也和run
与let
类似:
当 lambda 主要执行的是调用对象的方法和赋值时,建议使用
apply
;而当调用对象主要用作参数时,建议使用
also
;当 lambda 会用到类的
this
时,建议使用also
。
3. 更多的作用域函数
在 Kotlin 中,除了run
,let
,apply
,also
之外,还有其他高效的作用域函数。但另一方面掌握了这 4 个作用域函数,已经覆盖大部分使用场景。剩下的几个使用需求没有那么的迫切,但能掌握是更好咯,可以帮助写出更有 Kotlin 样的代码。
版权声明: 本文为 InfoQ 作者【子不语Any】的原创文章。
原文链接:【http://xie.infoq.cn/article/4cc21ffcdaa66b451ceedf1d6】。文章转载请联系作者。
评论