Kotlin和RxJava - 为什么我的Single.zip()没有编译?

tmn*_*tmn 23 kotlin rx-java

我在这里有点疯狂.我正在尝试创建一个Observable<BigDecimal>扩展函数(针对RxJava 2.x)来发出平均排放量,但是我得到了Single.zip()函数的编译错误.有没有人有任何想法我做错了什么?我试图明确我的所有类型,但是没有用......

import io.reactivex.Observable
import io.reactivex.Single
import java.math.BigDecimal


fun Observable<BigDecimal>.sum() = reduce { total, next -> total + next }

//compile error
fun Observable<BigDecimal>.average() = publish().autoConnect(2).let {
    Single.zip(it.sum().toSingle(), it.count()) {
        sum, count -> sum / BigDecimal.valueOf(count)
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Ste*_*ngo 37

类型推断通常不适用于rxJava2.实际上它不是类型推断问题.Kotlin通常生成用kotlin函数类型替换SAM的扩展方法,但由于某种原因,这种技术不适用于重写方法.

更多细节请访问https://youtrack.jetbrains.com/issue/KT-13609

作为选项,您可以尝试为lambda参数指定类型

fun Observable<BigDecimal>.average() = publish().autoConnect(2).let {
    Single.zip(it.sum().toSingle(), it.count(), BiFunction {
        sum: BigDecimal, count: Long ->
        sum / BigDecimal.valueOf(count)
    })
}
Run Code Online (Sandbox Code Playgroud)

  • @IzzoObella,在这种情况下,您需要使用Function3而不是BiFunction (2认同)

zsm*_*b13 9

类型推断由于某种原因失败,必须以某种方式在此上下文中推断出多种类型的组合.

您可以使用更传统(并且遗憾的是更详细)的语法显式指定类型,如下所示:

fun Observable<BigDecimal>.average() = publish().autoConnect(2).let {
    Single.zip(it.sum().toSingle(), it.count(), BiFunction<BigDecimal, Long, BigDecimal> {
        sum, count ->
        sum / BigDecimal.valueOf(count)
    })
}
Run Code Online (Sandbox Code Playgroud)

更新:

我刚刚发现了一个类似的问题,这里的实际问题是Kotlin无法推断出Single.zip你想要调用哪个超载.从官方文档:

如果Java类有多个采用功能接口的方法,则可以使用将lambda转换为特定SAM类型的适配器函数来选择需要调用的方法.这些适配器函数也是在需要时由编译器生成的.

所以事实证明,使用更明确的SAM构造函数本身就可以解决这个问题,并为您提供类型推断(基本上,我之前的答案是使用比实际需要更长的语法):

fun Observable<BigDecimal>.average(): Single<BigDecimal> = publish().autoConnect(2).let {
    Single.zip(it.sum().toSingle(), it.count(), BiFunction {
        sum, count ->
        sum / BigDecimal.valueOf(count)
    })
}
Run Code Online (Sandbox Code Playgroud)