美文网首页
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