我之前使用RxJava和Kotlin时遇到了一些问题。我做了一些有趣的发现,我仍然感到困惑。
RxJava中有简单的Func1
接口
public interface Func1<T, R> extends Function {
R call(T t);
}
我试图将扩展方法添加到Observable
,也是一个RxJava类。这会将排放量收集到Google Guava ImmutableListMulitmap
中,使用Func1
将关键字映射到每个项目。
fun <K,T> Observable<T>.toImmutableListMultimap(keyMapper: Func1<T, K>): Observable<ImmutableListMultimap<K,T>> {
return this.collect({ ImmutableListMultimap.builder<K,T>()},{ b, t -> b.put(keyMapper.call(t), t)}).map { it.build() }
}
当我尝试调用此扩展方法时,我无法进行编译,并且根本不理解lambda表达式。
ScheduledItem.all.flatMap { it.rebuildSoftTransactions }
.toImmutableListMultimap { it.id /*compile error */ } .cache()
然而,当我修改扩展方法以使用function type时,最奇怪的事情发生了。
fun <K,T> Observable<T>.toImmutableListMultimap(keyMapper: (T) -> K): Observable<ImmutableListMultimap<K,T>> {
return this.collect({ ImmutableListMultimap.builder<K,T>()},{ b, t -> b.put(keyMapper(t), t)}).map { it.build() }
}
然后一切都编好了。但这让我感到困惑:为什么它没有将lambda推断到界面上?当我在map()
上使用标准Observable
方法时,它使用大括号{ }
语法推断lambda。但为什么它不适用于我上面的扩展方法?
答案 0 :(得分:7)
SAM转换(将lambda转换为函数类型)目前仅适用于用Java编写的方法。 Kotlin具有适当的函数类型,因此不需要SAM转换 - 您可以直接将参数声明为函数类型(正如您所观察到的那样有效)。
Observable.map()
是用Java编写的,因此应用了SAM转换。你的扩展函数是用Kotlin编写的,所以不是。