Kotlin的5个主要作用域函数

 applay, also,let, run, with 是kotlin标准库提供的5个主要的作用域函数(Scope Functions)​,它们的设计目的是为了在特定作用域内更简洁地操作对象。

如何使用这5个函数,要从它的设计目的来区分:

  1. apply : 配置/对象初始化, 返回对象本身
  2. also : 副作用操作/链式中间处理,返回对象本身
  3. let : 空安全转换/数据映射,返回Lambda结果
  4. run : 对象计算/链式操作,返回Lambda结果
  5. with : 非扩展函数版的 run ,返回Lambda结果

深度解析每个函数

1.apply

public inline fun <T> T.apply(block: T.() -> Unit): T {block() // 配置对象return this // 返回自身
}

特点:

  • 隐式 this 引用
  • 专为对象初始化/配置设计
  • Lambda 是扩展函数​:可以直接访问对象成员
val dialog = AlertDialog.Builder(context).apply {setTitle("提示")setCancelable(false)}

这是一个非常典型的建造者模式。其内部的setTitle方法可能是这样的:

class Builder (private val context: Context) {private var title: String = ""fun setTitle(title: String) = apply {this.title = title}
}

上面的代码你可能看着有些奇怪 = apply {}

上面的代码等效于:

fun setTitle(title: String): Builder {this.title = titlereturn this
}

这里会引入一个概念单表达式函数(Single-Expression Functions)

fun add(a: Int, b: Int): Int {return a + b
}// 标准形式:用 = 替代 { return ... }
fun add(a: Int, b: Int): Int = a + b

在看上面 无论 block 里有多少行代码,apply{} ​本身是一个返回 this 的表达式​, 如果你还不理解

fun max(a: Int, b: Int){if (a > b)return aelse return b
}fun max(a: Int, b: Int): Int = if (a > b) a else b

它只是需要一个表达式,而apply{}恰好满足这个表达式 

无论 block 里有多少行代码,apply ​本身是一个返回 this 的表达式

val person = Person().apply {name = "John"      // this.name = "John"age = 30           // this.age = 30city = "New York"  // this.city = "New York"
}
这个是一个初始化的例子等价与
val person = Person()
person.name = "John"
person.age = 30
person.city = "New York"

2.also

public inline fun <T> T.also(block: (T) -> Unit): T {block(this) // 执行副作用return this // 返回自身
}

特点​:

  • 显式 it 引用, 让副作用操作更明确
  • 可空对象处理
  • 适合调试日志链式调用中的中间操作
  • Lambda 是普通函数​:必须通过 it 引用对象
phone?.also {require(it)//副作用 
}?.process()

 验证并继续使用原对象。判空如果不做类型转换建议使用also。

 

3.let

public inline fun <T, R> T.let(block: (T) -> R): R {return block(this) // 将 this 作为参数传入 lambda
}

特点​:

  • 用 it 引用对象
  • 适合可空对象处理类型转换
val length = phone?.let { it.length } ?: 0

它的行为是把一个String类型转换成了一个Int类型,类型转换是它的重点。

4.run

public inline fun <T, R> T.run(block: T.() -> R): R {return block() // 以扩展函数方式调用
}

特点​:

  • 用 this 引用对象
  • 可与 ?. 结合处理可空对象
  • 适合同时访问对象属性和返回计算结果
val description = user.run { "$name: ${calculateScore()}" }

5.with

public inline fun <T, R> with(receiver: T, block: T.() -> R): R {return receiver.block() // 非扩展函数版本
}

特点​:

  • 非扩展函数,需要显式传入接收者对象
  • 不能直接结合 ?. 处理可空对象​(需要额外判空)
  • 适合集中操作一个对象的场景
val result = with(config) {validate()buildResult()
}

我们可以看到这5个都是内联函数(inline functions),其核心机制就是在编译时进行代码拷贝(或称"代码展开"),而不是在运行时进行函数调用。

为什么 Kotlin 标准库函数用 inline?

  • 避免 lambda 对象创建​:如果不内联,每次调用都会生成一个匿名类实例
  • 支持 return 控制流​:内联后 lambda 中的 return 可以直接从外层函数返回

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/85051.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

原型模式Prototype Pattern

模式定义 用原型实例指定创建对象的种类&#xff0c;并且通过复制这些原型创建新的对象&#xff0c;其允许一个对象再创建 另外一个可定制的对象&#xff0c;无须知道任何创建的细节 对象创建型模式 基本工作原理是通过将一个原型对象传给那个要发动创建的对象&#xff0c;这…

基于深度学习的智能交通流量预测系统:技术与实践

前言 随着城市化进程的加速&#xff0c;交通拥堵问题日益严重&#xff0c;给人们的日常生活和经济发展带来了巨大的挑战。智能交通系统&#xff08;ITS&#xff09;作为解决交通问题的重要手段&#xff0c;逐渐成为研究的热点。其中&#xff0c;交通流量预测是智能交通系统中的…

Cilium动手实验室: 精通之旅---23.Advanced Gateway API Use Cases

Cilium动手实验室: 精通之旅---23.Advanced Gateway API Use Cases 1. Lab说明1.1 高级网关 API 使用案例 2. 负载均衡器2.1 部署应用程序2.2 部署 Gateway 和 HTTPRoute 3. HTTP 标头请求修饰符3.1 部署 HTTPRoute3.2 可观测性 4. HTTP 响应标头重写5. HTTP 流量镜像5.1 demo应…

Agentic Workflow是什么?Agentic Workflow会成为下一个AI风口吗?

无论是想要学习人工智能当做主业营收&#xff0c;还是像我一样作为开发工程师但依然要运用这个颠覆开发的时代宠儿&#xff0c;都有必要了解、学习一下人工智能。 近期发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;入行门槛低&#x…

Some chunks are larger than 500 KiB after minification. Consider

在 vue3vite 项目开发中&#xff0c;build 打包时出现以下警告报错&#xff1a; (!) Some chunks are larger than 500 KiB after minification. Consider: - Using dynamic import() to code-split the application - Use build.rollupOptions.output.manualChunks to improve…

NodeJS11和10以及之前的版本,关键差异?

Node.js 11 相比 10&#xff08;及更早版本&#xff09;&#xff0c;除了事件循环行为的重大改变&#xff0c;还有多个核心模块和底层机制的升级。以下是它们的关键差异和新特性对比&#xff0c;帮助你快速掌握两个版本的重要变化。 &#x1f527; 一、事件循环行为变化&#x…

调和级数 敛散性

调和级数的敛散性是一个非常经典的问题。我们来全面分析它。 &#x1f9e0; 调和级数定义 调和级数是指&#xff1a; ∑ n 1 ∞ 1 n 1 1 2 1 3 1 4 ⋯ \sum_{n1}^{\infty} \frac{1}{n} 1 \frac{1}{2} \frac{1}{3} \frac{1}{4} \cdots n1∑∞​n1​121​31​41​⋯ …

Python•元组集合字符串

ʕ⸝⸝⸝˙Ⱉ˙ʔ ♡ 元组&#x1f6e5;️创建访问修改解包其他操作比较的依据 集合&#x1f6f8;创建添加和删除其他操作 字符串&#x1fa82;创建索引和切片基本操作连接加号join() 重复查找in 关键字index()find()startswith()endswith() ​​替换​​分割​​大小写删除 能…

​​信息系统项目管理师-项目整合管理 知识点总结与例题分析​​

​​一、项目整合管理概述​​ ​​1. 定义与重要性​​ 项目整合管理是项目管理知识领域中的核心过程,它协调所有其他知识领域的过程和活动,确保项目各要素有效整合。其核心目标是: ​​统一项目目标​​:确保各要素服务于共同目标​​协调冲突​​:解决项目执行中的各…

『uniapp』onThemeChange监听主题样式,动态主题不正确生效,样式被覆盖的坑

目录 问题示例代码解决思路1&#xff08;缺点影响显示效果有延迟&#xff09;解决思路2——通过路由刷新页面&#xff08;缺点只适用于部分网页&#xff09;解决思路3——vuex&#xff08;没学会~&#xff09;总结 欢迎关注 『uniapp』 专栏&#xff0c;持续更新中 欢迎关注 『…

LeetCode 高频 SQL 50 题(基础版)【题解】合集

点击下方标题可跳转至对应部分&#xff1a; LeetCode 高频 SQL 50 题&#xff08;基础版&#xff09;之 【查询】部分 LeetCode 高频 SQL 50 题&#xff08;基础版&#xff09;之 【连接】部分 上 LeetCode 高频 SQL 50 题&#xff08;基础版&#xff09;之 【连接】部分 下…

Jenkins 全面深入学习目录

Jenkins 全面深入学习目录 第一部分&#xff1a;Jenkins 基础入门 Jenkins 概述 持续集成/持续交付(CI/CD)概念Jenkins 的历史与发展Jenkins 与其他 CI/CD 工具的比较 Jenkins 安装与配置 系统要求与环境准备不同操作系统下的安装方法初始配置与安全设置插件管理系统 Jenkins…

安装laravel11和laravel12的一些报错问题解决

前言 今天在安装laravel的过程中遇到一些报错问题&#xff0c;记录一下。 laravel 12 Root composer.json requires laravel/tinker ^2.10.1, found laravel/tinker[2.x-dev] but it does not match your minimum-stability laravel/framework[v12.0.0, ..., v12.15.0] requ…

Oracle21cR3之客户端安装错误及处理方法

文章目录 Oracle21cR3客户端安装1. 下载2. 安装解压到指定位置&#xff0c;如下&#xff1a;2. 安装 3. 常见错误1. 无法将 JINSHENGYUAN\jinshengyuan 安装用户添加到 %2% 组。1. 问题原因分析2. 处理方法 Oracle21cR3客户端安装 1. 下载 官网下载 2. 安装 解压到指定位置…

web3 资讯网址

1. 新闻 币圈导航| 区块链导航| WEB3导航 | 聚合币圈交易所、行情工具、空投资讯、DeFi入口及行业动态&#xff0c;一站式区块链资源门户网站 2.github位置 https://github.com/itgoyo/awesome-crypto

【C++】简单商品价格计算程序练习

相信你是最棒哒!!! 文章目录 一、题目代码 二、题目解析 1.解析版 2.简洁版 总结 一、题目代码 构建一个类book,其中含有两个私有数据成员qu和price,将price初始化为qu的10倍,建立一个有5个元素的数组对象,将qu初始化为6~10。要求通过对象指针访问对象数组,按相反的顺序…

现代数据工程实践:基于Dagster的ETL架构设计与实现

在当今数据驱动的世界中&#xff0c;有效的数据处理流程至关重要。本文将带您通过一个完整的教程&#xff0c;学习如何使用Dagster构建一个功能强大的ETL(提取、转换、加载)管道。无论您是数据工程师、分析师还是对数据流水线感兴趣的技术爱好者&#xff0c;本教程都将为您提供…

golang-linux环境配置

下载源码包 &#xff1a;All releases - The Go Programming Language 解压文件 sudo tar -zxvf go1.24.4.linux-amd64.tar.gz -C /usr/local/ 配置环境 vim ~/.bashrc 在配置文件最后加上下面三行&#xff1a; # 设置GO语言的路径 export GOROOT/usr/local/go # 当前go…

【模拟 贪心】B4207 [常州市赛 2021] 战士|普及+

B4207 [常州市赛 2021] 战士 题目背景 搬运自 http://czoj.com.cn/p/443。数据为民间数据。 题目描述 小 X \text X X 在玩一款操控战士和怪物战斗的游戏。战士初始生命值为 iH \text{iH} iH 、初始攻击力为 iA \text{iA} iA 。怪物只有一个&#xff0c;初始生命值为 H…

37-Oracle 23 ai Shrink Tablespace(一键收缩表空间)

小伙伴们有没有经历过&#xff0c;超大表和超大数据的导入后&#xff0c;数据被删除了&#xff0c;然而空间迟迟不释放&#xff0c;存储添置又跟不上&#xff0c;业务空间告警的时候。收缩就很必须了&#xff0c;然而收缩需谨慎&#xff0c;数据大过天。DBMS_SPACE.SHRINK_TABL…