This page looks best with JavaScript enabled

Kotlin let run apply with 方法

 ·  ☕ 2 min read
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
1
2
3
4
public inline fun <T, R> T.run(block: T.() -> R): R {
    //... 忽略中间部分
    return block()
}

run 的返回值是代码块的返回值

  • apply
1
2
3
4
5
public inline fun <T> T.apply(block: T.() -> Unit): T {
    //... 忽略中间部分
    block()
    return this
}

apply 的返回值是当前对象

  • let
1
2
3
4
public inline fun <T, R> T.let(block: (T) -> R): R {
    //... 忽略中间部分
    return block(this)
}

let 的返回值也是代码块的返回值,且会把当前对象作为参数传入,这个参数默认名字叫 it,也可以自己取名字

1
2
3
4
5
6
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
1
2
3
4
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    //... 忽略中间部分
    return receiver.block()
}

而且 let run apply 都是 T.xx 的方式定义,说明他们是作为任意对象的一个扩展函数使用,而with则是作为普通的顶层函数使用。


Yang
WRITTEN BY
Yang
Developer