Kotlin语言的run内置函数

221 阅读2分钟

在 Kotlin 中,run 是一个作用域函数(scope function),用于在对象的上下文中执行代码块,并返回结果

一、run 作为扩展函数

语法‌:对象.run { ... }
作用‌:在对象的上下文中执行代码块,返回 lambda 的结果。
特点‌:

  1. 内部通过 this 访问对象(可省略)。
  2. 常用于链式调用或对对象进行转换操作。

示例‌:

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

fun main() {
    val person = Person("Alice", 25)
    val result = person.run {
        // this 可以省略
        name = "Bob"   // 修改对象属性
        age += 1
        "姓名: $name, 年龄: $age"  // 返回字符串
    }
    println(result) // 输出:姓名: Bob, 年龄: 26
    println(person) // 输出:Person(name=Bob, age=26)
}

二、run 作为非扩展函数

语法‌:run { ... }
作用‌:直接执行代码块,返回 lambda 的结果,常用于需要临时作用域的场景。
特点‌:

  1. 无需对象即可调用。
  2. 适合在表达式需要的地方执行多行代码。

示例‌:

fun main() {
    val fullName = run {
        val firstName = "John"
        val lastName = "Doe"
        "$firstName $lastName" // 返回拼接后的字符串
    }
    println(fullName) // 输出:John Doe
}

三、run vs 其他作用域函数

函数接收者返回值典型用途
runthislambda 结果对象初始化 + 计算返回值
letitlambda 结果处理可空对象、链式操作
withthislambda 结果非扩展版本,需传入对象参数
applythis对象本身对象配置
alsoit对象本身附加操作(如日志)

四、使用场景

  1. 对象配置并计算结果
    当需要修改对象属性并返回计算结果时,run 非常高效:

    val personInfo = Person("Charlie", 30).run {
        age *= 2
        "加倍年龄后: $age"
    }
    
  2. 链式调用中的中间操作
    结合安全调用(?.)处理可空对象:

    val length = nullableString?.run {
        println("处理非空字符串: $this")
        length
    } ?: 0
    
  3. 替代临时变量
    在需要表达式的地方替代临时变量:

    val discount = run {
        val basePrice = 100
        val seasonMultiplier = 0.8
        basePrice * seasonMultiplier
    }
    
  4. 把上一个结果值自动给下一个函数

fun main() {
    val str = "Lilei is OK"

    // 下面是 具名函数 配合 run函数
    // 这个是属于具名函数  str.run(具名函数)
    str
        .run(::isLong) // this == str本身
        .run(::showText) // this == isLong返回的boolean值
        .run(::mapText)
        .run(::println)
    println()

    // let函数持有it,run函数持有this 都可以很灵活的,把上一个结果值 自动给 下一个函数
    str.let(::isLong) // it == str本身
    .let(::showText) // it == isLong返回的boolean值
    .let(::mapText) // it == str本身
    .let(::println) // it == str本身

    println()

    // >>>>>>>>>>>>>>>>>>>>>> 上面全部都是具名函数调用给run执行  下面全部是 匿名函数调  用给run执行
    str
        .run {
            if (length > 5) true else false
        }
        .run {
            if (this) "你的字符串合格" else "你的字符串不合格"
        }
        .run {
            "【$this】"
        }
        .run {
            println(this)
        }
}
fun isLong(str: String) /* : Boolean */ = if (str.length > 5) true else false

fun showText(isLong: Boolean) /*: String */ = if (isLong) "你的字符串合格" else "你的字符串不合格"

fun mapText(getShow: String) /*: String */ = "【$getShow】"


五、总结

  • 使用 对象.run 时,可以直接访问对象属性和方法(this 可省略)。
  • 使用 run { ... }(非扩展)时,适合快速生成一个作用域并返回结果。
  • 根据是否需要返回值或操作对象本身,选择 runapply 或其他作用域函数。

通过灵活使用 run,可以让代码更简洁且富有表达力。