Ada*_*old 5 java kotlin kotlin-multiplatform
我在 Kotlin 中遇到 SAM 问题。我正在开发一个具有接受 lambda 函数的库。我的问题是我不能简单地写这个:
fun myFun(someLambda: (A) -> B) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
因为如果 Java 用户想要调用它,他们需要将 a 传递Function1给它,这不是很好的用户体验。如果我创建一个 SAM:
fun myFun(someSam: Function<A, B>) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
那么对于 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)
}
})
}
Run Code Online (Sandbox Code Playgroud)
这种方法有很多样板,而且也很难维护。有更好的替代方案来解决这个问题吗?
我刚刚添加了方便的函数,使我能够轻松地将 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.
Run Code Online (Sandbox Code Playgroud)
假设您在 Kotlin 中有以下函数:
fun doSomething1(c : (String) -> Unit) : String = TODO()
fun doSomething2(f : (String) -> String) : String = TODO()
fun doSomething3(f : (String, String) -> String) : String = TODO()
Run Code Online (Sandbox Code Playgroud)
Java 的用法可能如下所示:
doSomething1($consume((e) -> System.out.println(e)));
doSomething2($((e) -> e + "ok"));
doSomething3($((e1, e2) -> String.join(", ", e1, e2)));
Run Code Online (Sandbox Code Playgroud)
请注意,我曾经$consume克服过有关 的歧义Function<T, R>。您也可以用于$消费者,但是您需要大括号或者必须将其强制转换为Consumer<T>-interace 才能利用方法引用,例如:
doSomething1($((e) -> { System.out.println(e); }));
doSomething1($((Consumer<String>) System.out::println));
Run Code Online (Sandbox Code Playgroud)
$使用反引号的主要好处是,在 Kotlin 中你可能不会使用它,因为它不太容易写(谁在调用函数时以反引号开头?)并且代码完成并不建议这样做就这么容易。
此外,$-sign 可以在 Java 端直接调用,没有问题。
也许您想将您的重载函数与此混合,这样您就不需要实现所有重载代码本身并将这些函数放在可供 Java 开发人员使用的自己的库中?
| 归档时间: |
|
| 查看次数: |
177 次 |
| 最近记录: |