首页 > 其他分享 >kotlin-run、with、apply、also、let

kotlin-run、with、apply、also、let

时间:2023-02-21 00:00:31浏览次数:45  
标签:run 函数 kotlin also let fun apply block

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

相关文章