Kotlin高阶函数和单方法接口的行为?

我之前在使用RxJava和Kotlin时遇到了一些问题。 我做了一些有趣的发现,我仍然感到困惑。

RxJava中有简单的Func1接口

 public interface Func1<T, R> extends Function { R call(T t); } 

我试图添加一个扩展方法到一个Observable ,也是一个RxJava类。 这将收集排放到谷歌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() 

然而,当我修改扩展方法使用函数类型时,发生了最奇怪的事情。

 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推到界面上呢? 当我在Observable上使用标准的map()方法时,它使用curly { }语法来推断lambda。 但为什么它不适用于我的扩展方法?

SAM转换(将lambda转换为函数类型)目前仅适用于用Java编写的方法。 Kotlin具有适当的函数类型,因此不需要SAM转换 – 您可以直接将函数类型声明为参数(正如您所观察到的那样)。

Observable.map()是用Java编写的,因此应用了SAM转换。 你的扩展功能是用Kotlin编写的,所以不是。