kotlin的作用域函数主要有run、with、apply、also、let
这几个函数的目的是:在对象的上下文中执行代码块。当对一个对象调用这样的函数并提供一个 lambda 表达式时,它会形成一个临时作用域。在此作用域中,可以访问该对象而无需其名称。
我们可以通过分析各个作用域函数的源码来了解他们各自的操作
这里先定义两个类,接下去要添加的函数均在class ExternInner 中添加
open class BaseInner(var baseValue: Int = 10) class ExternInner { var externValue = 8 // 接下去要讲解的代码均在这里添加 // 。。。。。。 }
一、run
在Standard.kt中有两个run函数,一个是直接的run函数,另一个是用扩展函数的方式来实现
1、直接的run函数
public inline fun <R> run(block: () -> R): R { return block() }
只是一个很简单的block调用然后返回block的结果,如下的例子注释所描述的,this的作用域是属于ExternInner
fun testRun() { val result = run { // 这里的this是ExternInner所以可以直接用this.xxxx // 当然了不加this也是可以,这里加this只是为了方便知道各个参数的作用域 this.externValue + 5 } println(result) }
2、使用扩展函数的run函数
public inline fun <T, R> T.run(block: T.() -> R): R { return block() }
从源码上看,跟直接的run只有在函数的头做了扩展函数的声明,那么我们看下是如何使用和需要注意哪里的
fun testRun1() { val b = BaseInner() val result = b.run { // 这里的run是BaseInner的扩展函数,所以this默认对应的是BaseInner的作用域 // externValue则不属于该block的this作用域,如果遇到命名冲突要加this的时候 // 则要像如下的方式加 this.baseValue + [email protected] } println(result) }
具体的注意事项跟用法在上面的testRun1中的注释已经说明了
二、with
public inline fun <T, R> with(receiver: T, block: T.() -> R): R { return receiver.block() }
从如上的with函数可以看出它本身不是扩展函数,我们可以直接调用;但是它的参数的block是一个扩展的block并且是receiver的扩展,with里面只是执行了return receiver.block() 的调用
fun testWith() { val b = BaseInner() val result = with(b) { this.baseValue + [email protected] } println(result) }
如上可以看出,with更像是一中的两个run的结合体:是直接的函数调用,block是扩展函数,返回的是block的返回值
三、apply
public inline fun <T> T.apply(block: T.() -> Unit): T { block() return this }
从上面的apply可以看出它是T的一个扩展函数,block也是T的一个扩展函数并且该block无返回值;最后apply返回T自身
fun testApply() { val b = BaseInner() b.apply { println(this.baseValue + [email protected]) }.apply { println("再次apply") } }
如上的打印结果是:
18
再次apply
因为apply是b的扩展函数所以this对应的是BaseInner
在apply之后又调用了apply是因为apply返回的是this指针即BaseInner对应的b
从第一到第三点提到的都是无参的block
四、also
public inline fun <T> T.also(block: (T) -> Unit): T { block(this) return this }
看着also跟apply的区别是apply的block是无参而also的block参数是this,其他都是一样
五、let
public inline fun <T, R> T.let(block: (T) -> R): R { return block(this) }
let和run的区别是run的block是无参而let的block参数是this,他们的返回值都是block给的返回值
总结:
with函数是:run全局函数和扩展run函数的结合体即:with是全局函数,with有一个receiver的传入参数和对应的receiver的扩展block函数;并且返回值都是block的返回值
apply函数:是T的扩展函数,对应的block是无参,返回值是this
also函数:跟apply函数几乎是一样的,唯一的区别是also对应的block传入参数是this
let函数:跟run函数几乎是一样的,是T的扩展函数,返回值是block的返回值;不同的是run的block没有传入参数而let的传入参数是this
标签:run,函数,kotlin,also,let,fun,apply,block From: https://www.cnblogs.com/czwlinux/p/17139475.html