RxKotlin collectInto() MutableList с использованием ссылок на методы
Следующий код - моя попытка преобразовать пример RxJava в Kotlin. Это должно собрать кучу Int
в MutableList
, но я получаю массу ошибок.
val all: Single<MutableList<Int>> = Observable
.range(10, 20)
.collectInto(::MutableList, MutableList::add)
Ошибки:
Error:(113, 36) Kotlin: Type inference failed: Not enough information to infer parameter T in inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableList<T>
Please specify it explicitly.
Error:(113, 49) Kotlin: One type argument expected for interface MutableList<E> : List<E>, MutableCollection<E> defined in kotlin.collections
Error:(113, 67) Kotlin: None of the following functions can be called with the arguments supplied:
public abstract fun add(element: Int): Boolean defined in kotlin.collections.MutableList
public abstract fun add(index: Int, element: Int): Unit defined in kotlin.collections.MutableList
Если я изменю ImmutableList::add
в ImmutableList<Int>::add
Я избавляюсь от аргумента типа ожидаемой ошибки, который заменяется на:
Error:(113, 22) Kotlin: Type inference failed: fun <U : Any!> collectInto(initialValue: U!, collector: ((U!, Int!) -> Unit)!): Single<U!>!
cannot be applied to
(<unknown>,<unknown>)
Это прямая копия следующего в Java:
Observable<List<Integer>> all = Observable
.range(10, 20)
.collect(ArrayList::new, List::add);
Я понимаю, что первая ошибка говорит мне, что это либо неверный тип, и мне нужно быть более точным (где?), Но я подумал, что ::MutableList
будет эквивалентно () -> MutableList<Int>
, Третья ошибка говорит мне, что он не может вызвать add()
методы с аргументами, но опять же я думал, что MutableList::add
эквивалентно { list, value -> list.add(value) }
, Четвертая ошибка говорит мне, что она не может определить типы, применяемые к collector
,
Если я вместо этого использую лямбда-выражение, ошибок нет:
val all: Single<MutableList<Int>> = Observable
.range(10, 20)
.collectInto(mutableListOf(), { list, value -> list.add(value) })
all.subscribe { x -> println(x) }
Я был бы признателен за некоторые комментарии о том, что я делаю неправильно со ссылками на методы, поскольку я явно что-то не так понял (просматривая справочник по языку Kotlin, мне интересно, есть ли в настоящее время даже языковая функция?). Очень признателен.
1 ответ
В первом примере вы пытаетесь применить сигнатуру метода collect
одному из collectInto
,
Это никогда не может работать, так как collect
ожидает Func0<R>
и Action2<R, ? super T>
а также collectInto
ожидает реальный объект и BiConsumer<U, T>
,
Ссылка на конструктор не может работать для collectInto
- вам нужен реальный объект (например, ваш mutableListOf()
вызов)
Вторая проблема заключается в том, что Котлин ожидает BiConsumer
объект, а не функция. Я не совсем уверен, почему. Очевидно, что Kotlin не может обрабатывать несколько обобщений для лямбда-ссылок и ссылки на функции из SAM-интерфейсов.
Поэтому вам нужно передать экземпляр BiConsumer
а не просто функция.
Вот почему я спросил в комментарии, уверены ли вы в сообщении об ошибке:
range(10, 20).collectInto(mutableListOf(), { l, i -> l.add(i) })
выдаст мне ошибку, пока
range(10, 20).collectInto(mutableListOf(), BiConsumer { l, i -> l.add(i) })
не будет.