kotlin作用域函数 let、run、with、also、apply

kotlin v2.3.0 官方文档https://kotlinlang.org/docs/scope-functions.html

参考官方文档,仅作学习记录用

几个函数作用类似,区别在于对对象的引用以及返回结果

|-------|------|----------------------|---------|
| 函数 | 对象引用 | 返回值 | 是否为扩展函数 |
| let | it | lambada result | yes |
| run | this | lambada result | yes |
| run | - | lambada result | no |
| with | this | ambada result | no |
| apply | this | context object(this) | yes |
| also | it | context object(this) | yes |

选择的简单指南:

非空判断:let

在局部范围内引入表达式作为变量:let

对象配置:apply

对象配置以及计算结果:run

需要表达式的运行语句(非扩展):run

附加效果:also

对对象进行分组函数调用:with

let :

上下文对象作为参数it,返回结果为lambda表达式结果(最后一行)

通常用在非空判断、引入局部变量便于代码阅读

Kotlin 复制代码
//非空判断
val str: String? = "Hello"   
//processNonNullString(str)       // compilation error: str can be null
val length = str?.let { 
    println("let() called on $it")        
    processNonNullString(it)      // OK: 'it' is not null inside '?.let { }'
    it.length
}

//局部变量
val numbers = listOf("one", "two", "three", "four")
val modifiedFirstItem = numbers.first().let { firstItem ->
    println("The first item of the list is '$firstItem'")
    if (firstItem.length >= 5) firstItem else "!" + firstItem + "!"
}.uppercase()
println("First item after modifications: '$modifiedFirstItem'")

with:(可以理解为 " with this object, do the following. "

上下文对象用作lambda接收器(this),返回结果为lambda表达式结果(最后一行)

当不需要使用返回的结果时,建议使用with来调用上下文对象上的函数

Kotlin 复制代码
val numbers = mutableListOf("one", "two", "three")
with(numbers) {
    println("'with' is called with argument $this")
    println("It contains $size elements")
}

另外也可以用with 根据 对象的属性或者方法计算出的结果 构建引用

Kotlin 复制代码
val numbers = mutableListOf("one", "two", "three")
val firstAndLast = with(numbers) {
    "The first element is ${first()}," +
    " the last element is ${last()}"
}
println(firstAndLast)

run:

上下文对象用作lambda接收器(this),返回结果为lambda表达式结果(最后一行)

run与with类似,但可以作为扩展函数使用,更像let,推荐当需要初始化对象并计算返回值时使用

Kotlin 复制代码
val service = MultiportService("https://example.kotlinlang.org", 80)

val result = service.run {
    port = 8080
    query(prepareRequest() + " to port $port")
}

// the same code written with let() function:
val letResult = service.let {
    it.port = 8080
    it.query(it.prepareRequest() + " to port ${it.port}")
}

也可以作为非扩展函数使用,可以理解为: " run the code block and compute the result. "

Kotlin 复制代码
val hexNumberRegex = run {
    val digits = "0-9"
    val hexDigits = "A-Fa-f"
    val sign = "+-"

    Regex("[$sign]?[$digits$hexDigits]+")
}

for (match in hexNumberRegex.findAll("+123 -FFFF !%*& 88 XYZ")) {
    println(match.value)
}

apply:

上下文对象用作lambda接收器(this),返回对象本身

推荐在不需要返回值并且对对象的属性进行操作时使用,最推荐的使用场景为对象初始化和配置

可以理解为" apply the following assignments to the object. "

Kotlin 复制代码
val adam = Person("Adam").apply {
    age = 32
    city = "London"        
}
println(adam)

另外一个使用场景是包含在多个调用链中,以进行更复杂的处理

Kotlin 复制代码
val numberList = mutableListOf<Double>()
numberList.also { println("Populating the list") }
    .apply {
        add(2.71)
        add(3.14)
        add(1.0)
    }
    .also { println("Sorting the list") }
    .sort()

also:(可以理解为" and also do the following with the object. ")

上下文对象作为参数it,返回对象本身

通常用于引用该对象作为参数时使用,

也可用于执行一些将上下文对象作为参数的操作,用于需要引用对象而不是其属性和函数的操作,或者不想在外部使用this引用时。

Kotlin 复制代码
val numbers = mutableListOf("one", "two", "three")
numbers
    .also { println("The list elements before adding new one: $it") }
    .add("four")

takeIf与takeUnless:

takeIf满足条件时返回对象本身,不满足时返回null

takeUnless满足条件时返回null,不满足时返回对象本身

相关推荐
心平气和量大福大13 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
码哥DFS13 小时前
构造函数、实例对象、对象原型 ----三者关系
开发语言·javascript·原型模式
quantdash_cc14 小时前
告别自建 Requests/BS4 网页爬虫:基于 QuantDash 搭建零维保的高性能量化行情流水线
开发语言·爬虫·python·pandas·量化·quantdash
ydd10010014 小时前
寻找两个正序数组的中位数 Java 题解,二分分割详解
java·开发语言
半亩码田14 小时前
C#转Python第3.1篇:Python 的 class 没有访问修饰符?面向对象的另一条路
开发语言·python·c#
Wzx19801215 小时前
python沙箱和docker沙箱你选对了吗?
开发语言·python·docker
牧羊人.33315 小时前
Python 办公自动化从入门到入土|09 数据容器之字典
开发语言·python
小僧景贤15 小时前
嵌入式C语言 第二篇:基础语法|嵌入式C与标准C的核心差异
c语言·开发语言·嵌入式c语言
阿pin15 小时前
Android随笔-AIDL
android·开发语言·aidl
LiLiYuan.16 小时前
【字符串常量池】
java·开发语言·面试