kotlin - 为什么可以将高阶函数的扩展函数参数调用为 Kotlin 中的普通函数?
问题描述
让我们考虑这段代码:
class Receiver
fun higherOrder(extensionBlock: Receiver.() -> Unit) {
Receiver().extensionBlock() // works
extensionBlock(Receiver()) // works
}
fun Receiver.extension() = Unit
fun f() {
Receiver().extension() // works
extension(Receiver()) // unresolved reference
}
在我看来,扩展的功能签名是Receiver.() -> Unit
,与参数相同extensionBlock
;即我们可以打电话higherOrder(Receiver::extension)
罚款。如果这是真的,我不明白为什么扩展函数和相同类型的参数之间的正常函数调用语法不一致。我实际上很高兴这extension(Receiver())
是不允许的,所以只有一种方法可以调用扩展函数。所以我想主要问题是为什么我可以extensionBlock(Receiver())
在extensionBlock
有扩展函数签名的时候做?
解决方案
这些示例是两个不同的东西:第一个是带有接收器的函数类型A.() -> B
,第二个是扩展函数。
1.带接收器功能:
TL; DR:A.() -> B
是不同的写作方式(A) -> B
。它不扩展任何东西。
带接收器和不带接收器的函数类型的非字面值是可以互换的,因此接收器可以代表第一个参数,反之亦然。例如,类型为 (A, B) -> C 的值可以在预期 A.(B) -> C 的地方传递或赋值,反之亦然:
val repeatFun: String.(Int) -> String = { times -> this.repeat(times) }
val twoParameters: (String, Int) -> String = repeatFun // OK
在您的情况下,应用于解释的代码如下所示:
val typeFunWithReceiver = Receiver.() -> Unit
val typeFunWithParam : (Receiver) -> Unit = typeFunWithReceiver // It does NOT extend Receiver
现在你提到它,我也确实感到困惑。即使在 kotlin 文档中,他们也提到了相似之处:
这种行为类似于扩展函数,它还允许您访问函数体内的接收器对象的成员。
2.扩展功能
TL;DR:通过函数A.funName() -> B
扩展类。它不是像以前那样的方法类型。A
funName()
Kotlin 提供了使用新功能扩展类的能力,而无需从类继承或使用装饰器等设计模式。