Kotlin 高阶函数和单一方法接口的行为?
Behavior with Kotlin Higher-Order Functions and Single-method interfaces?
我之前在使用 RxJava 和 Kotlin 时遇到了一些问题。我做了一些有趣的发现,但我仍然对此感到困惑。
RxJava 中有简单的Func1
接口
public interface Func1<T, R> extends Function {
R call(T t);
}
我试图向 Observable
添加一个扩展方法,还有一个 RxJava class。这会将排放物收集到 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 推断到接口上?当我在 Observable
上使用标准 map()
方法时,它使用大括号 { }
语法推断 lambda 就好了。但是为什么它对我上面的扩展方法不起作用?
SAM 转换(将 lambda 转换为函数类型)目前仅适用于用 Java 编写的方法。 Kotlin 具有适当的函数类型,因此无需 SAM 转换 - 您可以直接将参数声明为函数类型(正如您所观察到的那样有效)。
Observable.map()
写在Java中,所以应用了SAM转换。您的扩展函数是用 Kotlin 编写的,所以不是。
我之前在使用 RxJava 和 Kotlin 时遇到了一些问题。我做了一些有趣的发现,但我仍然对此感到困惑。
RxJava 中有简单的Func1
接口
public interface Func1<T, R> extends Function {
R call(T t);
}
我试图向 Observable
添加一个扩展方法,还有一个 RxJava class。这会将排放物收集到 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 推断到接口上?当我在 Observable
上使用标准 map()
方法时,它使用大括号 { }
语法推断 lambda 就好了。但是为什么它对我上面的扩展方法不起作用?
SAM 转换(将 lambda 转换为函数类型)目前仅适用于用 Java 编写的方法。 Kotlin 具有适当的函数类型,因此无需 SAM 转换 - 您可以直接将参数声明为函数类型(正如您所观察到的那样有效)。
Observable.map()
写在Java中,所以应用了SAM转换。您的扩展函数是用 Kotlin 编写的,所以不是。