简体   繁体   English

如何在 Kotlin 中使用带有 SAM 接口的 function 接收器类型

[英]How to use function receiver type with SAM interfaces in Kotlin

I'm coming from Java and am new to Kotlin.我来自 Java 并且是 Kotlin 的新手。 I try to understand how to use receiver type with lambdas specified as functional SAM interfaces .我试图了解如何将接收器类型与指定为功能性SAM 接口的 lambda 一起使用。

Let the code speak for itself.让代码自己说话。

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

How do I need to change the code to use the Delegator lambda with dynamic receiver?如何更改代码以将Delegator lambda 与动态接收器一起使用?

You can define the functions inside the Delegator as extension function, this way the receiver is passed as this to the lambda.您可以将Delegator内部的函数定义为扩展 function,这样接收器就this传递给 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() }

Alternatively, you can simply define the dynamic receiver with a typealias to achieve the same result.或者,您可以简单地使用typealias定义动态接收器以获得相同的结果。

typealias AliasDelegator<T, R> = T.() -> R

fun <T, R> invokeWithAliasSamInterface(receiver: T, fn: AliasDelegator<T, R>): R = fn.invoke(receiver)

On the use site, both approaches look the same.在使用站点上,两种方法看起来都是一样的。

fun main() {
    val result = invokeWithExtensionSamInterface("Foo") { length }
    println(result)

    val otherResult = invokeWithAliasSamInterface("Fizz") { length }
    println(otherResult)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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