Kotlin 高阶扩展函数 T.()

最近在学习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())
}

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

完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容