2016-01-04 9 views
5

以前はRxJavaとKotlinを使っていくつかの問題を抱えていました。私はまだ私が困惑しているいくつかの興味深い発見をしました。Kotlinの高次関数とシングルメソッドのインタフェースでの動作は?

私はRxJavaクラスも、Observableに拡張メソッドを追加しようとしていたRxJava

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

でシンプルなFunc1インタフェースがあります。これは、Func1を使用してGoogle 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() } 
} 

私はこの拡張メソッドを呼び出そうとしましたが、コンパイルできず、ラムダ式を全く理解できませんでした。私はfunction typeを使用するための拡張メソッドを変更したとき

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() } 
} 

そしてすべてがうまくコンパイルされました。しかし、これが私に困惑しています:どのようにしてラムダをインターフェイスに推論していないのですか? Observableの標準map()メソッドを使用すると、ラムダを中括弧{ }の構文を使用してうまく推定します。しかし、なぜ私の上記の拡張メソッドではうまくいかないのですか?

答えて

7

現在、SAM変換(ラムダを関数型に変換)は、Javaで記述されたメソッドに対してのみ機能します。 Kotlinは適切な関数型を持っているので、SAM変換の必要はありません。パラメータを関数型として直接宣言することができます(これは、あなたが観察したように機能します)。

Observable.map()はJavaで記述されているため、SAM変換が適用されます。拡張機能はKotlinで書かれているので、そうではありません。