在 Kotlin 中,是否可以调用成员扩展函数来指定发送对象和接收者?如果是这样,如何?

In Kotlin, is it possible to call a member extension function specifying both the object dispatched to and the receiver? If so, how?

考虑以下示例:

class C {
    fun ThirdPartyClass.f() {
        // Do stuff involving functions/properties from
        // both the C instance and the ThirdPartyClass receiver
    }

    fun someMethod(third: ThirdPartyClass) {
        // Do stuff...
        third.f()
        // Do stuff...
    }
}

C 中,在 ThirdPartyClass 的给定实例上调用 .f 没有问题。但是在 C 之外,给定 C 的实例 cThirdPartyClass 的实例 third,有没有办法调用 cf 接收者是 third

with (myC) { 
  myThirdPartyClass.f()
}

TL;DR:这是可能的 - 请参阅下面的 解决方案

相关语言信息

好像是spec provides relevant information under the overload resolution section (more specifically the receivers小节)。

来自规范:

Every function or property that is defined as a method or an extension has one or more special parameters called receiver parameters. When calling such a callable using navigation operators (. or ?.) the left hand side value is called an explicit receiver of this particular call. In addition to the explicit receiver, each call may indirectly access zero or more implicit receivers.

换句话说,一个方法总是有一个显式的接收者 - 这是调用它时将放在 . 之前的东西(或者不是,如果它可以隐式使用),以及零个或多个隐式周围范围提供的接收器(这在规范中有更详细的解释)。

在我们的示例中,f 具有类型 ThirdPartyClass 的显式接收器和类型 C.

的隐式接收器

此外:

For extension callables, the receiver used as the extension receiver parameter is called extension receiver, while the implicit receiver associated with the declaration scope the extension is declared in is called dispatch receiver. For a particular callable invocation, any or both receivers may be involved, but, if an extension receiver is involved, the dispatch receiver must be implicit.

这意味着无法在调用 f 显式 提供 C 接收器作为扩展接收器(ThirdPartyClass 类型) 涉及。

解决方案

但是只要 隐式 C 接收器在范围内,仍然可以调用该方法!这是 C 的其他方法中发生的情况(例如我们示例中的 someMethod),但它也发生在具有 C 接收器的函数(和 lambda)中,启用,例如:

with (c) { third.f() }