ZakTaccardi
ZakTaccardi

Reputation: 12467

How do I call a class's function that has a receiver?

How do I call a public extension function on a class that has a receiver?

interface CoroutineActivity {

    // how can I call this function in example below?
    fun CoroutineScope.onCreate(savedInstanceState: Bundle?)
}

class CoroutineActivityDelegate(private val coroutineActivity: CoroutineActivity) {

    fun onCreate(savedInstanceState: Bundle?) {

        val onCreateScope = CoroutineScope(Dispatchers.Main + Job())

        // how do I call an extension function with a receiver? This doesn't compile
        coroutineActivity.onCreate(onCreateScope, savedInstanceState)
    }
}

Is it possible? I'd prefer CoroutineScope to be the receiver, rather than the first parameter

Upvotes: 2

Views: 95

Answers (1)

hotkey
hotkey

Reputation: 147981

Yes, it is possible.

The function you described is said to have two receivers, a dispatch receiver of type CoroutineActivity and an extension receiver of type CoroutineScope.

While there's no syntax to call this function by directly providing the two receivers, it can be called in a scope of its dispatch receiver type (i.e. in a scope where this: CoroutineActivity). These scopes are:

  • scopes of members of CoroutineActivity and its subtypes;
  • scopes of extensions with the extension receiver of type CoroutineActivity (or its subtypes);
  • scopes of function literals (lambdas) with a receiver of type CoroutineActivity (or its subtypes).

In a suitable scope, you can simply call the function on an instance of CoroutineContext.

The simplest way to do that is to use the standard library scoping functions run { ... } or apply { ... }, passing a lambda with receiver as follows:

coroutineActivity.run { 
    val onCreateScope = CoroutineScope(Dispatchers.Main + Job())
    onCreateScope.onCreate(savedInstanceState)
}

Upvotes: 5

Related Questions