繁体   English   中英

如何解决 Kotlin 多平台库项目中的 lambda / SAM 问题?

[英]How to solve the lambda / SAM problem in Kotlin multiplatform library projects?

我在 Kotlin 中遇到 SAM 问题。 我正在开发一个库,该库具有接受 lambda 的函数。 我的问题是我不能简单地写这个:

fun myFun(someLambda: (A) -> B) {
    // ...
}

因为如果 Java 用户想调用它,他们需要将Function1传递给它,这不是很好的 UX。 如果我改为创建 SAM:

fun myFun(someSam: Function<A, B>) {
    // ...
}

那么对于 Kotlin 用户来说就很麻烦了。 到目前为止,我一直在做的是,我采用了 SAM 方式,并为 Kotlin 用户添加了所有这些功能的扩展功能,该功能仅转换为 SAM 功能:

inline fun <A, B> MyClass.someFun(crossinline fn: (A) -> B) {
    return someFun(object : Function<A, B> {
        override fun accept(value: A): B {
            return fn.invoke(value)
        }
    })
}

这种方法有很多样板,也很难维护。 有没有更好的选择来解决这个问题?

在 kotlin 1.4 中,您现在可以像这样声明函数式 (SAM) 接口:

fun interface MyFunction {
    fun doSomething(input: Int): Boolean
}

注意接口声明前面的“fun”关键字。 这将允许使用来自 kotlin 和 java 的 lambda。

另见https://kotlinlang.org/docs/reference/fun-interfaces.html

我只是添加了方便的函数,让我可以轻松地将 Java 函数式接口转换为它们的 Kotlin 对应物,但将它们放在反引号中(我不喜欢在常规 Kotlin 代码中看到(与测试相反);-)) ,例如:

fun <T> `$consume`(consumer: Consumer<T>): (T) -> Unit = consumer::accept
fun <T, R> `$`(func: java.util.function.Function<T, R>): (T) -> R = func::apply
fun <T, U, R> `$`(func: java.util.function.BiFunction<T, U, R>): (T, U) -> R = func::apply
// etc.

假设您在 Kotlin 中有以下功能:

fun doSomething1(c : (String) -> Unit) : String = TODO()
fun doSomething2(f : (String) -> String) : String = TODO()
fun doSomething3(f : (String, String) -> String) : String = TODO()

Java 的用法可能如下所示:

doSomething1($consume((e) -> System.out.println(e)));
doSomething2($((e) -> e + "ok"));
doSomething3($((e1, e2) -> String.join(", ", e1, e2)));

请注意,我使用$consume来克服有关Function<T, R>的歧义。 您也可以将$用于消费者,但是您将需要大括号或必须将其强制转换为Consumer<T> -interace 以利用方法引用,例如:

doSomething1($((e) -> { System.out.println(e); }));
doSomething1($((Consumer<String>) System.out::println));

使用带有反引号的$的主要好处是,在 Kotlin 中你可能不会使用它,因为它不是那么容易写(谁在调用函数时以反引号开头?)并且代码完成不建议就那么容易。

此外, $ -sign 可以在 Java 端直接调用,没有问题。

也许您想将重载函数与此混合使用,这样您就不需要自己实现所有重载代码并将这些函数放在 Java 开发人员可用的自己的库中?

暂无
暂无

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

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