Kotlin之作用域函数

作者: Taonce | 来源:发表于2018-10-28 19:11 被阅读23次
    kotlin

    作用域函数

    含义:Kotlin中对一个对象进行一系列操作的函数,写法上类似集合的操作符

    种类:runletalsoapplytakeIftakeUnlesswithrepeat


    第一类:有返回结果的

    举例:通过letrun函数输入一段话,letrun函数都是将参数中闭包的返回值当做自己的返回值给返回出来,具体看源码实现。

        // 都是有返回结果,但是let闭包有参数,可以用it指代对象
        // run没有闭包参数的,只能用this来指代对象
        val letResult = user.let { "let::{${it.javaClass}}" }
        println(letResult)
        // let::{class lambda.User}
    
        val runResult = user.run { "run::{${this.javaClass}}" }
        println(runResult)
        // run::{class lambda.User}
    

    letrun的源码:

    // let
    kotlin
    @kotlin.internal.InlineOnly
    public inline fun <T, R> T.let(block: (T) -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return block(this)
    }
    
    // run
    tlin.internal.InlineOnly
    public inline fun <T, R> T.run(block: T.() -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return block()
    

    通过源码可以看出,let参数block是有返回值的。run同理。但是let中是将T继续以参数的形式传给了block闭包,所以在let闭包中可以使用it来代替对象,而run却只能用this关键字。


    第二类:无返回结果

    举例:同样是通过alsoapply输出一句话,但是没有返回的是对象,不是闭包函数。具体看下面源码实现。

        // also、apply和let、run的区别在于闭包内的操作没有返回结果
        // also和let一致,有闭包参数,可以使用it
        // apply和run一致,没有闭包参数,只能使用this
        user.also {
            println("also::{${it.javaClass}}")
        }
        // also::{class lambda.User}
        user.apply {
            println("apply::{${this.javaClass}}")
        }
        // apply::{class lambda.User}
    

    源码:

    // also
    kotlin
    @kotlin.internal.InlineOnly
    @SinceKotlin("1.1")
    public inline fun <T> T.also(block: (T) -> Unit): T {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        block(this)
        return this
    }
    
    // apply
    @kotlin.internal.InlineOnly
    public inline fun <T> T.apply(block: T.() -> Unit): T {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        block()
        return this
    }
    

    also的源码一眼就能看到,block参数返回了一个Unit,函数是将调用者T给返回了。apply同理。itthis解释看上面letrun的解释。


    第三类:函数的闭包有返回值,但是为Boolean类型

    举例:通过takeIftakeUnless函数中的闭包结果进行判断,然后做出相应的操作。其中闭包返回值都为Boolean类型。

    // takeIf和takeUnless的闭包参数都会返回一个Boolean类型的值
    // takeIf内闭包为false时,taleIf执行完会返回一个null
    // takeUnless内闭包为true时,takeUnless执行完会返回一个null,和takeIf正好相反
    user.takeIf { it.name.isNotEmpty() }
                ?.also { println("name is {${it.name}}") }
                ?: println("name is null")
    user.takeUnless { it.name.isNotEmpty() }
                ?.also { println("name is null") }
                ?: println("name is {${user.name}}")
    

    源码:

    @kotlin.internal.InlineOnly
    @SinceKotlin("1.1")
    public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
        contract {
            callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
        }
        return if (predicate(this)) this else null
    }
    

    通过上面takeIf的源码if (predicate(this)) this else null可以看出,如果闭包的返回值为false,那么函数就会返回一个null

    takeUnless正好与之相反。


    第四类:循环执行函数

        repeat(2) {
            println("count is $it,name is ${user.name}")
        }
        // count is 0,name is taonce
        // count is 1,name is taonce
    

    repeat函数不仅仅用于集合中,它的适用范围是任意对象,需要传入两个参数:times: Int, action: (Int) -> Unittimes是循环的次数,action就是闭包。通过上面的例子就能知道,闭包的执行次数有times确定。


    第五类:顶层函数

        with(user) {
            this.name = "kotlin"
            println("user name is ${user.name}")
        }
        // user name is kotlin
    

    with比较特殊,它不是通过对象调用使用的,而是把对象作为参数传入的。适用场景,对同一个对象进行相同的操作。比如一个TextView和一个Button都需要显示文字内容为开始,就可以用with同步操作:

    with(view) {
        this.text = "开始"
    }
    

    只需要这么写就可以完全同意处理了。

    with也是有返回值的,它和letrun很像,最大的不同在于with的参数,可以对同一类型的对象进行相同的操作,比如上面对TextViewButton的操作,如果换做是letrun就不行了,因为它们是通过对象调用的方法。


    写在最后

    每个人不是天生就强大,你若不努力,如何证明自己,加油!

    Thank You!

    --Taonce

    如果你觉得这篇文章对你有所帮助,那么就动动小手指,扫描下方的二维码,关注一波吧~~非常期待大家的加入

    专注Kotlin知识的公众号

    相关文章

      网友评论

        本文标题:Kotlin之作用域函数

        本文链接:https://www.haomeiwen.com/subject/fprmtqtx.html