apply,是一个扩展函数,在代码块中,对象被引用为this,并返回该调用对象本身。常用于对象的初始化和配置,尤其是在创建对象后立即设置其属性。
允许我们在不重复对象名的情况下设置其属性并最终返回配置好的对象。
data class Person(var name: String = "", var age: Int = 0)
val person = Person().apply {
name = "Alice"
age = 30
}
println(person) // 输出为 Person(name=Alice, age=30)
also,是一个扩展函数,在代码块中,与apply不同,also将对象作为参数传递给代码块(默认命名为it而不是this),并返回该对象本身。常用于在对象创建或配置后执行一些额外的操作(日志记录、验证的副操作)。
val person = Person().apply {
name = "Alice"
age = 30
}.also {
println("Person created: $it") //在对象配置后进行额外的验证
}
let,是一个扩展函数,在代码块中,let将调用对象作为参数传递给代码块(默认命名为it),并返回代码块的最后一行而非该对象本身。常结合安全调用操作符 ?. 处理可空对象,以避免空指针异常。
val nameLength = person?.let {
it.name.length
}
println(nameLength) // 输出: 5
run,有两种形式
1.作为对象的扩展函数:类似于apply,但返回的是代码块的最后一行而不是对象本身,对象的引用也为this。
2.不带对象的版本:直接执行一个代码块并返回代码块的最后一行,类似于一个立即执行的lambda表达式。适合执行独立的代码块
// 作为扩展函数
val ageSquared = person.run {
age * age
}
println(ageSquared) // 输出: 900
// 不带对象的版本
val result = run {
val a = 5
val b = 10
a + b
}
println(result) // 输出: 15
with,不是扩展函数,它接收一个对象和一个代码块,代码块中对象的引用为this,类似于apply,并返回代码块的最后一行。
val description = with(person) {
"Name: $name, Age: $age"
}
println(description) // 输出: Name: Alice, Age: 30
接下来对这些作用域函数的区别和使用场景做一个总结: