You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin作用域函数场景选择、it与this差异及存在意义咨询

Kotlin作用域函数:关键字差异、适用场景解析
fun main() {
    val person = Person()
    person.let {
        it.name = "let HelloWorld"
        println(it.name)
        println("let $it")
    }
    println("let.. $person")
    with(person) {
        name = "With HelloWorld"
        println(this.name)
        println(this)
    }
    println(person)
    person.run {
        name = "Run HelloWorld"
        println(this.name)
        println(this)
    }
    println(person)
    person.apply {
        name = "apply HelloWorld"
        println(this.name)
        println(this)
    }
    println(person)
    person.also {
        it.name = "Also HelloWorld"
        println(it.name)
        println(it)
    }
    println(person)
}

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

一、it与this的核心差异

Kotlin作用域函数的核心区分点在于上下文对象的指代逻辑:

  • it:仅用于let和also,上下文对象是以lambda参数的形式传入。你可以给它重命名(比如person.let { p -> p.name = ... }),避免变量名冲突。示例中let和also块里的it就是指代person对象。
  • this:用于with、run和apply,上下文对象作为lambda的接收者(相当于处于对象的成员方法内部)。你可以省略this直接调用对象成员(比如示例中with块里的name = "With HelloWorld"),用this明确指代上下文对象。

二、为什么需要多种作用域函数?

这些函数看似功能重叠,但核心差异在于返回值类型和上下文指代方式,对应不同的编程场景需求:

  • 部分函数返回上下文对象本身(apply、also),适合链式调用或对象初始化流程;
  • 部分函数返回lambda的执行结果(let、run),适合对象转换或结果计算;
  • 还有的专门用于非空安全处理(let配合?.),或简化同一对象的多成员操作(with)。
    这种设计让代码语义更清晰,不同场景下选对函数能大幅提升代码可读性和简洁度。

三、各作用域函数的适用场景

1. let

  • 上下文指代:it(参数)
  • 返回值:lambda最后一行的执行结果
  • 适用场景:
    • 非空对象处理:person?.let { ... },避免空指针异常;
    • 对象转换:将一个对象转换为另一种类型(比如val nameLength = person.let { it.name.length });
    • 临时作用域限制:在lambda内临时处理对象,避免污染外部作用域。

2. with

  • 上下文指代:this(接收者)
  • 返回值:lambda最后一行的执行结果
  • 适用场景:
    • 对同一对象执行多成员操作,无需重复书写对象名;
    • 注意:with是顶层函数,不是对象扩展函数,使用前需确保对象非空,否则会抛出空指针异常。

3. run

  • 上下文指代:this(接收者)
  • 返回值:lambda最后一行的执行结果
  • 适用场景:
    • 结合let和with的优势:既支持非空调用(person?.run { ... }),又能像with一样省略this操作成员;
    • 执行多步操作并返回结果,比如初始化对象后计算某个衍生值。

4. apply

  • 上下文指代:this(接收者)
  • 返回值:上下文对象本身
  • 适用场景:
    • 对象初始化:链式设置对象属性(比如val person = Person().apply { name = "Alice"; age = 25 });
    • 对象配置:修改已有对象后直接返回,适合链式调用(比如person.apply { age += 1 }.let { println(it.age) })。

5. also

  • 上下文指代:it(参数)
  • 返回值:上下文对象本身
  • 适用场景:
    • 执行额外操作(比如日志打印)且不改变对象本身,适合链式调用;
    • 复制对象后修改属性,同时保留原对象引用;
    • 与apply的区别:also用it指代,适合需要明确区分上下文对象和其他变量的场景,避免this歧义。

内容的提问来源于stack exchange,提问作者Ruchir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 11:30:13