关于rx java:Kotlin和RxJava-为什么我的Single.zip()无法编译?

Kotlin and RxJava - Why is my Single.zip() not compiling?

我在这里有点疯狂。我正在尝试创建一个Observable<BigDecimal>扩展函数(与RxJava 2.x相对)来发出发射的平均值,但是我在Single.zip()函数中遇到了编译错误。有人知道我在做什么错吗?我也尝试对所有类型都进行显式的显示,但这没有用...

1
2
3
4
5
6
7
8
9
10
11
12
13
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)
    }
}

enter image description here


类型推断在rxJava2中通常不起作用。实际上,这不是类型推断问题。 Kotlin通常会生成扩展方法,以用Kotlin功能类型替换SAM,但是由于某种原因,该技术无法用于替代方法。

此处有更多详细信息https://youtrack.jetbrains.com/issue/KT-13609

作为一种选择,您可以尝试指定lambda参数的类型

1
2
3
4
5
6
fun Observable<BigDecimal>.average() = publish().autoConnect(2).let {
    Single.zip(it.sum().toSingle(), it.count(), BiFunction {
        sum: BigDecimal, count: Long ->
        sum / BigDecimal.valueOf(count)
    })
}


由于某种原因类型推断失败,在这种情况下必须可以某种方式推断出多种类型的组合。

您可以使用更传统(不幸的是更冗长)的语法显式指定类型,如下所示:

1
2
3
4
5
6
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)
    })
}

更新:

在解决类似问题时,我发现这里的实际问题是Kotlin无法推断您要呼叫的Single.zip重载。根据官方文档:

If the Java class has multiple methods taking functional interfaces,
you can choose the one you need to call by using an adapter function
that converts a lambda to a specific SAM type. Those adapter functions
are also generated by the compiler when needed.

因此,事实证明,使用更明确的SAM构造函数可自行解决此问题,并为您提供类型推断(基本上,我以前的回答是使用比实际所需的语法更长的语法):

1
2
3
4
5
6
fun Observable<BigDecimal>.average(): Single<BigDecimal> = publish().autoConnect(2).let {
    Single.zip(it.sum().toSingle(), it.count(), BiFunction {
        sum, count ->
        sum / BigDecimal.valueOf(count)
    })
}


如果类型推断是问题,则您可以做的一件事是使用RxKotlin

1
implementation"io.reactivex.rxjava2:rxkotlin:$rxKotlinVersion"

RxKotlin特别提供SAM帮助器,以帮助缓解类型推断问题。

在这种情况下,

1
Singles.zip(..., ...)

将能够毫无歧义地正常工作。请注意,我使用的是Singles而不是Single