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



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

RxJava 中有一个简单的Func1接口

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

我试图向Observable添加一个扩展方法,也是一个RxJava类。这将使用Func1将排放物收集到谷歌Guava ImmutableListMulitmap中,以映射每个项目的关键。

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()方法时,它会使用花括号{ }语法来推断lambda。但是为什么它不适用于我上面的扩展方法呢?

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

Observable.map()是用Java编写的,因此应用了SAM转换。您的扩展函数是用Kotlin编写的,所以它不是。

最新更新