Kotlin之作用域函数let、also、with、run、ap
2021-03-21 本文已影响0人
w达不溜w
1.let
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
作用:调用某个对象的let函数,则将该对象为函数的参数,在函数块中用it替代该对象。返回值为函数块的最后一行。
适用场景:(1)处理一个可null对象,统一判空处理;(2)明确一个变量所处特定作用域范围内可用
data class User(val name: String, val age: Int)
private var user: User? = null
fun main() {
// user=User("bestchangge",18)
user?.let {//①判断user不为null的条件下才会执行let函数体
//②it代表user对象,通过it可以访问其属性和方法
println("姓名:${it.name} —— 年龄:${it.age}")
}
}
2.also
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
}
also适用于let的任何场景,与let不同的是返回了this(表示对象本身),可以对传入的对象进行操作,可以用于链式调用
data class User(var name:String="",var age: Int=0)
private var user: User? = null
fun main() {
user=User()
user?.also {
it.name="bestchangge"
it.age=18
}
}
3.with
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
}
作用:非扩展函数,将对象作为函数的参数,在函数块内可以通过this指代该对象,返回函数最后一行
适用场景:同一个对象多个方法时,可以省去类名重复,直接调用方法即可。
data class User(val name: String, val age: Int)
private var user: User? = null
fun main() {
user=User("bestchangge",18)
with(user!!){
//可以省去对象名user
println("姓名:${name} —— 年龄:${age}")
}
}
4.run
扩展函数方式 T.run{}
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
非扩展函数run{}
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
run函数可以说是let和with的结合体,弥补了let函数在函数块内必须用it替代对象,又弥补了with函数传入对象判空的问题。
user?.run{
println("姓名:${name} —— 年龄:${age}")
}
5.apply
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
可以看到apply返回了this(对象本身),可以将apply包含到调用链中,这唯一一点和run函数不同。
apply函数适用于:对象初始化的时候,需要对对象中的属性进行赋值。
data class User(var name:String="",var age: Int=0)
private var user: User? = null
fun main() {
user=User()
user?.apply {
name="aa"
age=81
}
}
6.小结
(let)null场景,特定作用域 —> 升级版(also)返回this,可操作传入的对象
(with)省去类名直接调方法
—>升级版(run)let和with结合体,省去类名和传入对象判空的问题
—>升级版(apply)返回对象本身,可以操作对象
另:takeIf满足条件返回this,否则返回null;takeUnless不满足条件返回this,否则返回null