【问题标题】:RxKotlin collectInto() MutableList using method referencesRxKotlin collectInto() MutableList 使用方法引用
【发布时间】:2017-06-16 18:51:46
【问题描述】:

以下代码是我尝试将 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&lt;Int&gt;::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 将等同于() -&gt; MutableList&lt;Int&gt;。第三个错误告诉我它不能用参数调用任何add() 方法,但我再次认为MutableList::add 等同于{ list, value -&gt; list.add(value) }。第四个错误告诉我它无法确定应用于collector 的类型。

如果我改用 lambda 表达式,则没有错误:

val all: Single<MutableList<Int>> = Observable
        .range(10, 20)
        .collectInto(mutableListOf(), { list, value -> list.add(value) })

all.subscribe { x -> println(x) }

我会感谢一些 cmets 说明我在方法引用方面做错了什么,因为很明显我误解了一些东西(查看 Kotlin Language Reference,我想知道此时它是否甚至是一种语言功能?)。非常感谢。

【问题讨论】:

  • 确定 lambdas 不会出现同样的错误吗?因为我明白了……

标签: kotlin method-reference rx-kotlin


【解决方案1】:

在您的第一个示例中,您尝试将 collect 的方法签名应用于来自 collectInto 的方法签名。

这永远行不通,因为collect 需要一个Func0&lt;R&gt; 和一个Action2&lt;R, ? super T&gt;collectInto 需要一个真实对象 和一个BiConsumer&lt;U, T&gt;
构造函数reference 不能用于collectInto - 你需要一个真实的对象(例如你的mutableListOf() 调用)

第二个问题是 Kotlin 期望的是 BiConsumer 对象而不是函数。我不太清楚为什么。显然 Kotlin 无法处理来自 SAM 接口的 lambda 和函数引用的多个泛型。

因此,您需要传递BiConsumer 的实例,而不仅仅是一个函数。
这也是我在评论中询问您是否确定错误消息的原因:

range(10, 20).collectInto(mutableListOf(), { l, i ->  l.add(i) }) 

会给我一个错误,而

range(10, 20).collectInto(mutableListOf(), BiConsumer { l, i ->  l.add(i) })

不会。

【讨论】:

  • 感谢您的解释。通过阅读,我得出了类似的结论,尽管可能不是这样的技术术语!我没有错误;你使用的是什么版本的 Kotlin?我有 1.1.2-5。
  • Here's 这个例子的完整实现。
  • @amb85 我也在用 1.1.2-5¯_(ツ)_/¯
  • 谁知道?! ¯\_(ツ)_/¯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-19
  • 2021-06-05
  • 2019-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多