Kotlin 作用域函数(let、run、with、apply、also)对比

Kotlin 的 作用域函数(Scope Functions) 是简化代码逻辑的重要工具,它们通过临时作用域为对象提供更简洁的操作方式。以下是 let、run、with、apply、also 的对比分析:


一、核心区别对比表

函数 上下文对象引用 返回值 是否扩展函数 典型使用场景
let it Lambda 结果 是 非空对象处理、链式操作
run this Lambda 结果 是 对象配置 + 结果计算
with this Lambda 结果 否 对象的多属性操作
apply this 对象本身 是 对象初始化配置
also it 对象本身 是 对象附加操作(如日志、验证)

二、详细对比与使用场景

1. let
kotlin 复制代码
val result = obj.let { 
    // 操作 it 对象,返回最后一行结果
    it.doSomething()
    "Result" 
}
  • 特点 :
    • 通过 it 引用上下文对象,避免与外部作用域的 this 冲突。
    • 处理可空对象 :配合 ?. 安全调用(obj?.let { ... })。
    • 链式操作:将对象转换为其他结果。
2. run
kotlin 复制代码
val result = obj.run { 
    // 直接访问 this(可省略),返回最后一行结果
    doSomething()
    "Result"
}
  • 特点 :
    • 结合了 with 的作用域和 let 的扩展函数特性。
    • 同时操作对象属性并返回结果:适合对象配置后立即计算结果的场景。
3. with
kotlin 复制代码
val result = with(obj) {
    // 直接访问 this(可省略),返回最后一行结果
    doSomething()
    "Result"
}
  • 特点 :
    • 非扩展函数,直接传入对象。
    • 批量操作对象属性:例如初始化对象或对对象进行多次修改。
4. apply
kotlin 复制代码
val obj = MyClass().apply { 
    // 直接访问 this(可省略),返回对象本身
    name = "Kotlin"
    age = 10
}
  • 特点 :
    • 返回对象本身,适合对象初始化或链式配置。
    • 类似建造者模式(Builder Pattern)。
5. also
kotlin 复制代码
val obj = MyClass().also { 
    // 通过 it 引用对象,返回对象本身
    println("Created: $it")
}
  • 特点 :
    • 执行副作用操作:如打印日志、验证数据,但不修改对象。
    • 链式调用中插入额外操作。

三、选择依据

  1. 是否需要返回对象本身?

    • 是 → apply 或 also。
    • 否 → let、run、with。
  2. 上下文对象引用方式

    • 需要显式名称(避免 this 冲突) → let、also(使用 it)。
    • 隐式访问属性 → run、with、apply(使用 this)。
  3. 处理可空性

    • 使用 ?.let 安全处理可空对象。
  4. 是否需要扩展函数?

    • 是 → 排除 with。

四、经典示例

kotlin 复制代码
// let:处理可空对象 + 转换结果
val length = nullableString?.let { 
    it.trim().length 
} ?: 0

// apply:对象初始化
val person = Person().apply {
    name = "Alice"
    age = 30
}

// also:链式调用插入日志
val list = mutableListOf(1, 2, 3)
    .also { println("Initial list: $it") }
    .apply { add(4) }
    .also { println("Updated list: $it") }

通过理解上下文引用方式、返回值和典型场景,可以更精准地选择合适的作用域函数,提升代码简洁性和可读性。

相关推荐
Zhao-Jichao9 分钟前
AI Prompting for Everyone 课程笔记 - P17 图像生成 Imaging Generation
前端
Mikko718 分钟前
Redis 连接数满了服务端有错误信息吗?连接数不增加却命令超时?6.2 实测连接池、超时与大 key 怎么判定
java·spring boot·redis·后端
.Bryce.25 分钟前
从零到一开发技术名词大全:从需求分析到 AI Agent 工程
java·网络·人工智能·agent·需求分析·agent评测
SL_staff36 分钟前
JVS-APS的7个刚性约束设计:从无限产能幻觉到可执行排产的工程实践
java·spring cloud·全栈
Highcharts.js1 小时前
智能数据分析组件Orbit 正式发布与快速上手体验教程
前端·人工智能·信息可视化·数据分析系统·highcharts·orbit·智能可视化
螺丝钉tina1 小时前
[Playwright ][16]Playwright + TypeScript API 自动化测试实战:API测试
前端·javascript·typescript
代码山河2 小时前
基本类型转换:自动类型转换与强制类型转换
java·学习·架构·教程·面向对象·项目
小天源2 小时前
智叟云集系统 · 架构与职责分层
服务器·前端·数据库
俩个逗号。。3 小时前
Kotlin flow 详解
android·开发语言·kotlin
Escalating_xu3 小时前
【Linux 网络编程】五种 I/O 模型与非阻塞 I/O:从“等数据”到正确处理 EAGAIN
java·linux·网络