Vengo de Java y soy nuevo en Kotlin. Trato de entender cómo usar el tipo de receptor con lambdas especificadas como interfaces SAM funcionales.
Deja que el código hable por sí mismo.
fun interface Delegator <T> { fun delegate(receiver: T) } fun <T> invokeWithDynamicReceiver(receiver: T, fn: T.() -> Unit) = receiver.fn() fun <T> invokeWithSamInterface(receiver: T, fn: Delegator<T>) = fn.delegate(receiver) fun dynamicReceiver() { invokeWithDynamicReceiver("Foo") { length } // Dynamic receiver invokeWithSamInterface("Foo") { it.length } // Can't bind receiver as "this" } ¿Cómo necesito cambiar el código para usar Delegator lambda con receptor dinámico?
Puede definir las funciones dentro del Delegator como función de extensión, de esta manera el receptor se pasa this a la lambda.
fun interface ExtensionDelegator <T, R> { fun T.delegate(): R } fun <T, R> invokeWithExtensionSamInterface(receiver: T, fn: ExtensionDelegator<T, R>): R = with(fn) { receiver.delegate() } Alternativamente, puede simplemente definir el receptor dinámico con un typealias para lograr el mismo resultado.
typealias AliasDelegator<T, R> = T.() -> R fun <T, R> invokeWithAliasSamInterface(receiver: T, fn: AliasDelegator<T, R>): R = fn.invoke(receiver)En el sitio de uso, ambos enfoques tienen el mismo aspecto.
fun main() { val result = invokeWithExtensionSamInterface("Foo") { length } println(result) val otherResult = invokeWithAliasSamInterface("Fizz") { length } println(otherResult) }