Kotlin的五个高阶函数: with,also,apply,let,run。
Differences between apply/with/let/also/run
inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
inline fun <T> T.also(block: (T) -> Unit): T {
block(this)
return this
}
inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
inline fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
inline fun <T, R> T.run(block: T.() -> R): R {
return block()
}
Examples:
val r: R = T().run { this.foo(); this.toR() }
val r: R = with(T()) { this.foo(); this.toR() }
val t: T = T().apply { this.foo() }
val t: T = T().also { it.foo() }
val r: R = T().let { it.foo(); it.toR() }
When to use apply/with/let/also/run
apply
Use the apply() function if you are not accessing any functions of the receiver within your block, and also want to return the same receiver. This is most often the case when initializing a new object.
also
Use the also() function, if your block does not access its receiver parameter at all, or if it does not mutate its receiver parameter. Don’t use also() if your block needs to return a different value.
let
Use the let() function in either of the following cases:
- execute code if a given value is not null
- convert a nullable object to another nullable object
- limit the scope of a single local variable
with
Use with() only on non-nullable receivers, and when you don’t need its result.
run
Use run() function if you need to compute some value or want to limit the scope of multiple local variables. Use run() also if you want to convert explicit parameters to implicit receiver.
Combining Multiple Scoping Functions
尽量不使用嵌套的scope函数,会降低代码的可读性。
但是,使用链式调用,有时会提高代码的可读性。
private fun insert(user: User) = SqlBuilder().apply {
append("INSERT INTO user (email, name, age) VALUES ")
append("(?", user.email)
append(",?", user.name)
append(",?)", user.age)
}.also {
print("Executing SQL update: $it.")
}.run {
jdbc.update(this) > 0
}
参考:
Kotlin Scoping Functions apply vs. with, let, also, and run
Kotlin Standard Scoping Functions
网友评论