美文网首页
Kotlin 高阶扩展函数 T.()

Kotlin 高阶扩展函数 T.()

作者: 小白彡 | 来源:发表于2020-06-19 13:00 被阅读0次

    最近在学习kotlin扩展函数时碰到一个这样的写法:

    public inline fun <T> T.apply(block: T.() -> Unit): T {
    

    按正常来说,这个高阶函数的方法应该这样写:

    public inline fun <T> T.apply(block: (T) -> Unit): T {
    

    表示接收一个 参数类型为 T 无返回值的方法。

    但用T.() 代替 (T) 有什么特殊的地方呢??

    先看看为StringBuilder类定义一个正常的扩展函数:

    inline fun StringBuilder.add(str : (StringBuilder) -> Unit){
        str(this)
    }
    

    这个扩展函数接收一个 参数值为 StringBuilder 无返回值的函数。
    看一下调用:
    原始写法:

     StringBuilder().add(fun(sb :StringBuilder){
                sb.append(123)
                sb.append(456)
                sb.append(789)
            })
    

    运行结果:


    QQ截图20200619124455.png

    当然,在kotlin中方法参数是可以用lambda表达式代替的
    简化如下:

      StringBuilder().add({sb ->
                sb.append(123)
                sb.append(456)
                sb.append(789)
             })
    

    当参数只有一个时,可以不用声明
    再次简化:


    QQ截图20200619124831.png

    运行结果:


    QQ截图20200619124455.png

    可以看到运行结果都是一致的,而最后,我们传入的参数,可以用kotlin默认提供的it来代替。

    再次回到开始的问题,那T.()会变成什么样子呢?
    改一下看看:

    inline fun StringBuilder.add(str : StringBuilder.() -> Unit){
        str(this)
        println(this.toString())
    }
    

    调用:


    QQ截图20200619124931.png

    可以看到 原来的it不见了, 转而用this代替了,于是我们就可以这么写:


    QQ截图20200619125030.png

    从这里可以看出 (T) 和 T.() 这两种写法不同之处在于 :
    使用(T) 调用时默认使用it指代参数。
    使用 T.() 调用时默认使用this指代参数。
    后者代码更少了。

    于是联想到kotlin中的标准函数let(), applay()
    它们一个是it 一个是this 看看它们内部实现是怎样的:

    let():

    public inline fun <T, R> T.let(block: (T) -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return block(this)
    }
    

    applay()

    public inline fun <T> T.apply(block: T.() -> Unit): T {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        block()
        return this
    }
    

    可以看到它们中一个用的是(T) 一个用的是T.() 正好和前面吻合。

    而且使用T.()这种方式, 在调用函数时,有两种方式:

    inline fun StringBuilder.add(str : StringBuilder.() -> Unit){
        //1.
    //    str(this)
        //2.
        this.str()
    
        println(this.toString())
    }
    

    这两种调用方式输出的结果是一致的,第二种方式相对来说还是有点难以接受的~~~

    完。

    相关文章

      网友评论

          本文标题:Kotlin 高阶扩展函数 T.()

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