
在 Standard.kt 标准库中提供了一些便捷的内置高阶函数,可以帮助我们写出更简洁高效的代码。这些函数都是在一个对象上执行一个代码块,形成一个临时作用域可以访问该对象而无需其名称,不同的是这个对象在代码块中如何使用以及整个表达式的返回值是什么。
| 参数的使用方式 | 返回值的是什么 | 选哪个作用域函数 | |
| 参数 T.( ) :Lambda的接收者,即 this。 对象自我配置(调用自身成员属性函数)。 | 返回T,即接收者对象。 | apply | |
| 返回R,即Lambda的值。 | 扩展函数 | run | |
| 普通函数 | with | ||
| 参数 T :Lambda的参数,即 it。 当作参数被别人使用。 | 返回T,即接收者对象。 | also | |
| 返回R,即Lambda的值。 | let | ||
| 无参数。 语句替代表达式。 | run | ||
apply说明:调用该对象的类成员,返回该对象。
场景:可以看作是一个配置函数,调用该对象的成员属性和成员函数对其进行配置,最后返回该对象。
//源码 public inline funT.apply(block: T.() -> Unit): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() return this }
//未使用
val student1 = Student()
student1.id = 123
student1.name = "张三"
student1.setPositiom("班长")
//使用后
val student2 = Student().apply {
id = 123456
name = "李四"
setPositiom("团支书")
}
also说明:该对象当做参数被别人使用,返回该对象。
场景:
public inline funT.also(block: (T) -> Unit): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block(this) return this }
let说明:该对象当做参数被别人使用,返回Lambda的值。
场景:
public inline funT.let(block: (T) -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block(this) }
举例:在Activity或Fragment传参时。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param = it.getString(ARG_PARAM)
}
}
with说明:调用该对象的类成员,返回Lambda的值。
场景:
public inline funwith(receiver: T, block: T.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return receiver.block() }
举例:
with(recyclerView) {
layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
adapter = mAdapter
}
run说明:无参数,返回Lambda的值。
场景:
public inline funrun(block: () -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } public inline fun T.run(block: T.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }
repeat原理:将 action 函数执行 times 次。
public inline fun repeat(times: Int, action: (Int) -> Unit) {
contract { callsInPlace(action) }
for (index in 0 until times) {
action(index)
}
}
takeIf原理:predicate 返回 true 则返回调用者对象,否则返回 null。
场景:类似于加强版的 if 表达式,可以让对象使用安全调用符 ?. 调用。
public inline funT.takeIf(predicate: (T) -> Boolean): T? { contract { callsInPlace(predicate, InvocationKind.EXACTLY_ONCE) } return if (predicate(this)) this else null }
举例:
fun filterUser1(user: User?) {
if (user != null && user.age > 18 && user.sex == "male") {
println(user.toString())
}
}
fun filterUser2(user: User?) {
user?.takeIf {
it.age > 18 && it.sex == "male"
}.apply {
println(toString())
}
}
takeUnless原理:功能和 takeIf 相反,predicate 返回 false 则返回调用者对象,否则返回 null。
public inline funT.takeUnless(predicate: (T) -> Boolean): T? { contract { callsInPlace(predicate, InvocationKind.EXACTLY_ONCE) } return if (!predicate(this)) this else null }
TODO用来标记待办,会抛异常,可以指定异常原因。
public inline fun TODO(): Nothing = throw NotImplementedError()
public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason")