如何在 Kotlin 中将函数接收器类型与 SAM 接口一起使用

Posted

技术标签:

【中文标题】如何在 Kotlin 中将函数接收器类型与 SAM 接口一起使用【英文标题】:How to use function receiver type with SAM interfaces in Kotlin 【发布时间】:2022-01-08 21:56:16 【问题描述】:

我来自 Java,并且是 Kotlin 的新手。我试图了解如何将receiver type 与指定为功能SAM interfaces 的lambda 一起使用。

让代码自己说话。

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"

如何更改代码以将Delegator lambda 与动态接收器一起使用?

【问题讨论】:

【参考方案1】:

您可以将Delegator 中的函数定义为扩展函数,这样接收者将作为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() 

或者,您可以简单地使用typealias 定义动态接收器以实现相同的结果。

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

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

在使用网站上,这两种方法看起来是一样的。

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

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

【讨论】:

以上是关于如何在 Kotlin 中将函数接收器类型与 SAM 接口一起使用的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中将匿名类型转换为键/值数组?

如何在 RxJava 2 和 Kotlin 中将 null 传递给具有可空类型的 Observable

Kotlin带接收者的lambda表达式

Kotlin标准库函数 ③ ( with 标准库函数 | also 标准库函数 )

Kotlin进阶系列-函数类型及函数字面值

如何使用 kotlin 在 android studio 中将按钮与网站链接