Поведение с функциями высшего порядка Котлина и интерфейсами с одним методом?

Раньше у меня возникали проблемы с использованием RxJava и Kotlin. Я сделал несколько интересных открытий, о которых я все еще озадачен.

В Func1 есть простой интерфейс Func1

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

Я пытался добавить метод расширения к Observable , также к классу RxJava. Это позволит собрать выбросы в 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() } } 

Когда я попытался вызвать этот метод расширения, я не смог его скомпилировать, и он вообще не понимал выражение лямбда.

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

И тогда все составило отлично. Но это меня озадачило: почему это не привело лямбда к интерфейсу? Когда я использую стандартный метод map() в Observable он отлично описывает лямбда, используя синтаксис curly bracket { } . Но почему это не работает для моего метода расширения выше?

Преобразование SAM (преобразование лямбда в тип функции) в настоящее время работает только для методов, написанных на Java. Kotlin имеет соответствующие типы функций, поэтому нет необходимости в преобразовании SAM – вы можете объявить параметр как тип функции напрямую (что работает, как вы заметили).

Observable.map() написан на Java, поэтому применяется преобразование SAM. Ваша функция расширения написана в Котлине, так что это не так.