当前位置: 首页 > news >正文

Kotlin 作用域函数全解析:let、run、with、apply、also 应该怎么选?

Kotlin 提供了一套优雅的“作用域函数”(Scope Functions),包括:letrunwithapplyalso。它们看起来相似,行为上也有交集,但却各有侧重。掌握它们的使用场景,不仅能让代码更简洁,还能让意图更加明确。


📌 什么是作用域函数?

作用域函数的作用是:在一个对象的上下文中执行一段代码块,并返回某个结果

所有作用域函数的行为可以分成两方面:

分类内容
上下文对象访问方式通过 this 还是 it 来引用对象
返回值类型返回原始对象,还是返回 lambda 表达式的最后一行结果

🧩 总览对比表

函数访问方式返回值是否扩展函数常见用途
letitlambda 结果可空判断、链式转换、局部作用域
runthislambda 结果表达式计算、初始化逻辑
withthislambda 结果对已有对象进行多次操作
applythis对象本身初始化对象属性链式构建
alsoit对象本身调试、日志、链式副作用

🧪 逐个详解 + 示例

1. let:适合可空对象链式处理

let 最大的特点是使用 it 访问对象,并返回 lambda 表达式最后的值,常用于安全调用、转换或临时作用域。

val name: String? = "Kotlin"val length = name?.let {println("名字是:$it")it.length
}

常见用途:

  • 安全调用链(null 安全)
  • 表达式转换(如 map)
  • 限定临时作用域变量名(如 it 改为具体名)

2. run:适合表达式求值或初始化计算

run 使用 this 引用对象,返回表达式的结果。可以用于对象配置,也可以直接作为代码块返回值。

val result = "Hello".run {println("原字符串是 $this")length + 10
}

常见用途:

  • 表达式求值
  • 对象初始化后立即使用

3. with:适合已有对象的多次操作

with 不是扩展函数,而是一个普通函数。它的写法比较自然,像在“带着对象做事情”。

val builder = StringBuilder()
val result = with(builder) {append("Hello, ")append("World!")toString()
}

常见用途:

  • 构造复杂对象时,连续操作对象属性
  • 避免重复写对象名

4. apply:返回对象自身,用于构建对象

apply 使用 this 引用对象,返回对象本身。常用于构造函数 + 初始化链式调用。

val user = User().apply {name = "Alice"age = 20
}

常见用途:

  • 初始化对象并配置属性
  • DSL(领域特定语言)构建,如 View.apply {}

5. also:副作用处理,不改变原值

also 使用 it 引用对象,返回对象本身。适合用于打印、日志、调试、不影响主逻辑的操作。

val numbers = mutableListOf("one", "two", "three").also { println("原始数据:$it") }.apply { add("four") }

常见用途:

  • 日志打印
  • 调试时插入查看变量值
  • 链式调用中临时操作对象

🎯 使用建议:如何选择?

你可以用以下口诀快速判断:

  • 🤔 我需要结果?run / with / let
  • 🛠️ 我要改对象?apply / with
  • 🧪 我想插入副作用?also
  • 可能为 null??.let
  • 📦 要链式构建对象?apply

🧠 小技巧:记住两个维度

返回谁?
- 返回对象本身:apply, also
- 返回表达式结果:let, run, with用谁访问对象?
- this:apply, run, with
- it:let, also

http://www.xdnf.cn/news/290197.html

相关文章:

  • C++演讲比赛案例代码
  • [人机交互]理解与概念化交互
  • 小工具功能强大,非常优秀!​
  • 「Mac畅玩AIGC与多模态20」开发篇16 - 使用结构化输出字段控制后续流程示例
  • 基于STM32F103C8T6驱动WS2812彩灯模块点亮RGB灯
  • 布隆过滤器
  • Qt学习笔记
  • SVD降维详解
  • 领略算法真谛: 多源bfs
  • 设一个测试情境,新用户注册后显示的名字不完整,测试思路是怎么样的?
  • 项目实战-基于信号处理与SVM机器学习的声音情感识别系统
  • 【Bootstrap V4系列】学习入门教程之 组件-按钮组(Button group)
  • MAC地址与帧结构
  • ICLR2024 | GNS-HFA | 通过梯度归一化缩放和高频适应增强视觉Transformer的可迁移对抗攻击
  • WMS仓库管理系统:Java+Vue,含源码及文档,集成仓储全流程管控,实现库存精准、作业高效、数据透明
  • Visual Studio 项目转Qt项目
  • 用网页显示工控仪表
  • Barrett Reduction算法优化:更紧的界限消除冗余的减法
  • 迅睿CMS导入别站数据库
  • 【瞎折腾/mi50 32G/ubuntu】mi50显卡ubuntu运行大模型开坑(二)使用llama.cpp部署Qwen3系列
  • 卡尔曼滤波详解
  • 从Excel到高级工具:数据分析进阶指南
  • # 部署深度学习模型:Flask API 服务端与客户端通信实战
  • Linux进程间的通信
  • Node.js 是什么?
  • docker 外部能访问外网,内部不行(代理问题)
  • SQL常见误区
  • 如何扫描系统漏洞?漏洞扫描的原理是什么?
  • 【MCP Node.js SDK 全栈进阶指南】专家篇(1):MCP-SDK扩展与定制
  • Dify本地 + vllm + Qwen