Kotlin 之 let、with、run、apply、also 函数的使用

一、内联拓展函数 let

let 扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,let函数的是一个不错的选择;let函数另一个作用就是可以避免写一些判断null的操作。

1.1 let 函数的使用的一般结构

object.let {
    it.todo() //在函数体内使用it替代object对象去访问其公有的属性和方法
    ...
}

//另一种用途 判断object为null的操作
object?.let { //表示object不为null的条件下,才会去执行let函数体
    it.todo()
}

1.2 let函数底层的inline扩展函数+lambda结构

@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

意思就是 T 类型的对象调用 let 方法,实际调用的是传入 let 方法的 lambda 表达式的 block 块,最终返回 lambda 表达式的返回值。
lambda 表达式内部通过 it 指代该对象。

1.3 let 函数常见的适用的场景

  • 场景一: 最常用的场景就是使用let函数处理需要针对一个可null的对象统一做判空处理。
  • 场景二: 然后就是需要去明确一个变量所处特定的作用域范围内可以使用
obj?.funA()
obj?.funB()
obj?.funC()

obj?.let {
    it.funA()
    it.funB()
    it.funC()
}

二、内联函数 with

2.1 with 函数使用的一般结构

with(object) {
    //todo
}

2.2 with 函数底层的inline扩展函数+lambda 结构

@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

注意,这个 with 函数不是拓展函数,它接收两个参数,第一个参数是要是用的对象,第二个参数是一个 lambda 表达式,该方法实际调用的是第一个参数对象,进行 block 块的调用,
最终返回 lambda 表达式的返回值。
lambda 表达式内部通过 this 指代该对象。

2.3 with 函数的适用的场景

适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上。

obj.funA()
obj.funB()
obj.funC()

with(obj) {
    this.funA()
    funB() // this 可省略
    funC)
}