简体   繁体   中英

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

Consider the following example:

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...
    }
}

Within C , there's no problem calling .f on a given instance of ThirdPartyClass . But outside C , given an instance c of C and an instance third of ThirdPartyClass , is there a way to invoke c 's f with third as the receiver?

with (myC) { 
  myThirdPartyClass.f()
}

TL;DR : it's possible - see how under Solution below.

Relevant language information

It seems the spec provides relevant information under the overload resolution section (more specifically the receivers subsection).

From the spec:

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.

In other words, a method always has an explicit receiver - which is what will be placed before the . when calling it (or not, if it can be used implicitly), and zero or more implicit receivers provided by surrounding scopes (this is explained in greater detail in the spec).

In our example, f has an explicit receiver of type ThirdPartyClass , and an implicit receiver of type C .

Furthermore:

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.

This means there's no way to provide the C receiver explicitly when calling f , as an extension receiver (of type ThirdPartyClass ) is involved.

Solution

But the method can still be called whenever an implicit C receiver is in scope! This is what happens within other methods of C (such as someMethod in our example), but it also happens within functions (and lambdas) with a C receiver, enabling, eg:

with (c) { third.f() }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM