Quiero que mi función de extensión tenga un par de receptores. Por ejemplo, quiero que el handle de función pueda llamar a métodos de instancias de CoroutineScope e Iterable :
fun handle() { // I want to call CoroutineScope.launch() and Iterable.map() functions here map { launch { /* ... */ } } }Pensé que esto podría funcionar:
fun <T> (Iterable<T>, CoroutineScope).handle() {}Pero me da error:
Function declaration must have a nameSé que puedo crear la función con parámetros, pero
¿Es posible tener múltiples receptores para una sola función y cómo hacerlo sin parámetros?
Hasta donde yo sé, actualmente esto es imposible para los tipos que no controlamos. Hay planes para agregar dicha función, se procesa bajo KEEP-259 .
No sé cuál es la hoja de ruta planificada o cuándo podríamos esperar que se agregue, pero espero que veamos al menos algunos adelantos este año.
Este es un caso muy limitado, pero si su caso de uso es que tiene una función de orden superior en la que desea que el código en la lambda tenga múltiples receptores, y si los tipos que desea combinar son interfaces, puede crear una clase que envuelve las interfaces como delegados. Dentro de la lambda pasada a la siguiente función, puede llamar a las funciones Iterable y CoroutineScope.
class CoroutineScopeAndIterable<T>( private val coroutineScope: CoroutineScope, private val iterable: Iterable<T> ): CoroutineScope by coroutineScope, Iterable<T> by iterable suspend fun <T> CoroutineScope.runSomething( iterable: Iterable<T>, block: suspend CoroutineScopeAndIterable<T>.() -> Unit ) { CoroutineScopeAndIterable(this, iterable).block() }Aquí hay una solución que puede usar:
val <T> Iterable<T>.handle: CoroutineScope.() -> Unit get() = { map { launch { } } }