前言

Kotlin 标准库函数 runapplyletalsowith 简单对比。

主要是太容易忘记了,因此记录于此。(AI整理)

这五个函数本质上都是作用域函数(Scope Functions),区别只在于三点:

  1. 是不是扩展函数

  2. 对象怎么引用(it / this

  3. 返回什么(对象本身 / Lambda 结果)

只要抓住这三点,就不会再混淆。

正文

下面依次介绍怎么使用。

let

inline fun <T, R> T.let(block: (T) -> R): R

特点

  • 对象作为参数传入:it

  • 返回 Lambda 的最后一行

  • 非常适合空安全处理

示例 1:空安全处理

val list: List<Int>? = arrayListOf(1, 2, 3)
list?.let {
    println(it.size)
    it.map { value -> value * 2 }
}

示例 2:数据转换 / 映射

val name: String? = "Kotlin"
val length = name?.let { it.length }
println(length) // 6

示例 3:链式转换

val result = "123"
    .let { it.toInt() }
    .let { it * 2 }

println(result) // 246

适用场景

  • object?.let { } 判空

  • 数据转换 / 映射

  • 限制变量作用域

run

inline fun <T, R> T.run(block: T.() -> R): R

特点

  • this 访问对象(可省略)

  • 返回 Lambda 结果

  • = with + let 的结合体

示例 1:基本使用

val result = "biumall.com".run {
    println(isEmpty())
    length
}
println(result) // 8

示例 2:空安全 + 组合属性

data class User(val firstName: String, val lastName: String)

val user: User? = User("Kotlin", "Dev")
val fullName = user?.run { "$firstName $lastName" }
println(fullName) // Kotlin Dev

示例 3:链式处理

val size = listOf(1, 2, 3)
    .run { filter { it > 1 } }
    .size

println(size) // 2

适用场景

  • 对对象进行计算

  • 需要返回值

  • 想避免 it,又想判空

val name = user?.run { "$firstName $lastName" }

with

inline fun <T, R> with(receiver: T, block: T.() -> R): R

特点

  • 不是扩展函数

  • 对象作为参数传入

  • this 访问对象

  • 返回 Lambda 结果

示例 1:基本使用

val student = Student("大神", 20)
val result = with(student) {
    println(name)
    println(age)
    91
}

示例 2:Android 常见写法

with(textView) {
    text = "Hello"
    textSize = 16f
    setTextColor(Color.BLACK)
}

示例 3:计算结果

data class Person(val name: String, val age: Int)

val person = Person("Tom", 18)
val score = with(person) {
    if (age > 16) 100 else 60
}
println(score) // 100

适用场景

  • 对同一个对象多次访问属性/方法

  • Android 中 RecyclerView.onBindViewHolder 很常见

缺点:不支持空安全调用(?.with {} 不存在)

apply

inline fun <T> T.apply(block: T.() -> Unit): T

特点

  • this 访问对象

  • 始终返回对象本身

  • 非常适合「配置对象」

示例 1:集合初始化

val list = ArrayList<Int>().apply {
    add(1)
    add(2)
    add(3)
}

示例 2:View 配置

val textView = TextView(context).apply {
    text = "Hello"
    textSize = 16f
    setTextColor(Color.BLACK)
}

示例 3:对象构建

data class User(var name: String = "", var age: Int = 0)

val user = User().apply {
    name = "Kotlin"
    age = 10
}

典型场景

  • 对象初始化

  • Builder 模式简化

  • View / Model 配置

val textView = TextView(context).apply {
    text = "Hello"
    textSize = 16f
    setTextColor(Color.BLACK)
}

also

inline fun <T> T.also(block: (T) -> Unit): T

特点

  • 使用 it 指代对象

  • 返回对象本身

  • 不影响主流程,只「顺手做事」

示例 1:打印日志

val name = "biumall.com".also {
    println("长度:${it.length}")
}

示例 2:链式调用中插入副作用

val user = getUser()
    .also { logUser(it) }
    .apply { saveToDb(this) }

示例 3:调试 / 埋点

val file = File("test.txt")
    .also { println("文件路径:${it.path}") }
    .also { it.createNewFile() }

典型场景

  • 日志 / 埋点

  • 调试

  • 链式调用中插入副作用

val user = getUser()
    .also { logUser(it) }
    .apply { saveToDb(this) }

小结

想改对象用 apply,想顺手做事用 also,想算结果用 run,想判空处理用 let,想少写对象名用 with

函数是否为扩展函数对象引用返回值典型用途
letitLambda 结果判空、映射、链式转换
runthisLambda 结果对象计算、结果返回
withthisLambda 结果对同一对象多次操作
applythis对象本身对象初始化、配置
alsoit对象本身链式调用、日志、埋点

参考文章

  1. Kotlin中的特殊函数简介

  2. AI

相关文章

笔友城堡 - 可定义的个人主页

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

none
暂无评论...