Kotlin 提供了一些内置扩展方法, 能减少创建局部变量, 进而减少代码量, 常见的有 let
run
apply
with
等.
下面, 通过代码实例看下它们之间的区别:
实例
class Test {
data class Man(val name: String, val argOne: String = "456")
private val argOne = "123"
fun print() {
Man("stefan").let {
println(it.name) // it 代表 let 的调用方: Man
println(this.argOne) //123 this 代表 print 方法的属主: class Test
println(argOne) //456 隐式调用 this 同上一行
println(it.argOne) //456
}
Man("stefanJ").run {
println(this.name) // this 代表 run 的调用方: Man
println(this.argOne) //456
println(argOne) //456 隐式调用 this,所以是 Man 中的 argOne
}
Man("stefanJi").apply {
println(this.name) // this 代表 apply 的调用方: Man
println(this.argOne) //456
println(argOne) //456 隐式调用 this
}
with(Man("stefanJiJ")) {
println(this.name) // this 代表 with 接收的对象
println(this.argOne) //456
println(argOne) //456
}
}
}
从上面的例子可以看出,let
run
apply
他们的本质区别是代码块里的能拿到的执行对象不一样:
let
是通过it
拿到当前执行对象run
通过this
apply
通过this
但是 run
和 apply
貌似没有差别,既然名字不一样,肯定还是有差别的,看看他们的签名:
run
public inline fun <T, R> T.run(block: T.() -> R): R {
//... 忽略中间部分
return block()
}
run 的返回值是代码块的返回值
apply
public inline fun <T> T.apply(block: T.() -> Unit): T {
//... 忽略中间部分
block()
return this
}
apply 的返回值是当前对象
let
public inline fun <T, R> T.let(block: (T) -> R): R {
//... 忽略中间部分
return block(this)
}
let 的返回值也是代码块的返回值,且会把当前对象作为参数传入,这个参数默认名字叫 it
,也可以自己取名字
Man("stefan").let { man ->
println(man.name) // man 代表 let 的调用方: Man
println(this.argOne) //123 this 代表 print 方法的属主: class Test
println(argOne) //456 隐式调用 this 同上一行
println(man.argOne) //456
}
with
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
//... 忽略中间部分
return receiver.block()
}
而且 let
run
apply
都是 T.xx
的方式定义,说明他们是作为任意对象的一个扩展函数使用,而with
则是作为普通的顶层函数使用。