5

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

Func1RxJava中有简单的接口

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

我试图向Observable一个 RxJava 类添加一个扩展方法。这会将排放物收集到 Google GuavaImmutableListMulitmap中,并使用 aFunc1映射每个项目的密钥。

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 推断到接口上?当我在它上使用标准map()方法时,Observable它可以使用花括号{ }语法很好地推断出 lambda。但是为什么它不适用于我上面的扩展方法呢?

4

1 回答 1

7

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

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

于 2016-01-04T08:44:23.230 回答