2016-01-04 12 views
5

Wcześniej miałem problemy z RxJavą i Kotlinem. Zrobiłem kilka interesujących odkryć, o których wciąż jestem zaskoczony.Zachowanie z funkcjami wyższego rzędu w kotlinach i interfejsami opartymi na pojedynczej metodzie?

Istnieje prosty interfejs Func1 w RxJava

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

Próbowałem dodać metodę rozszerzenia do Observable, również klasy RxJava. To by zbierało emisje do Google Guava ImmutableListMulitmap używając Func1, aby odwzorować klucz z każdego przedmiotu.

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

Kiedy próbowałem wywołać tę metodę rozszerzenia nie mogę zmusić go do kompilacji, a nie było zrozumienia wyrażenia lambda w ogóle.

ScheduledItem.all.flatMap { it.rebuildSoftTransactions } 
.toImmutableListMultimap { it.id /*compile error */ } .cache() 

Jednak najdziwniejsze stało, kiedy zmodyfikował metodę rozszerzenia do korzystania z 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() } 
} 

A następnie wszystko skompilowane dobrze. Ale to mnie zaintrygowało: dlaczego to nie wpłynęło na interfejs lambda? Kiedy używam standardowej metody map() na Observable, to w łatwy sposób uzyskujemy lambdę, używając składni nawiasów klamrowych { }. Ale dlaczego nie działa dla mojej metody rozszerzenia powyżej?

Odpowiedz

7

Konwersja SAM (konwertowanie lambda na typ funkcji) działa obecnie tylko dla metod napisanych w języku Java. Kotlin ma odpowiednie typy funkcji, więc nie ma potrzeby konwersji SAM - możesz zadeklarować parametr bezpośrednio jako typ funkcji (co działa, jak zauważyłeś).

Observable.map() jest napisany w Javie, więc stosowana jest konwersja SAM. Twoja funkcja rozszerzenia jest napisana w Kotlin, więc nie jest.

Powiązane problemy