我在这里有点疯狂。我试图创建一个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)
}
}
答案 0 :(得分:33)
类型推断通常不适用于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)
})
}
答案 1 :(得分: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)
})
}
更新:
我在处理类似问题时发现,实际问题是Kotlin无法推断出您试图调用的Single.zip
超载。来自official documentation:
如果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)
})
}
答案 2 :(得分:0)
如果类型推断是问题所在,您可以做的一件事是使用RxKotlin
implementation "io.reactivex.rxjava2:rxkotlin:$rxKotlinVersion"
RxKotlin特别提供SAM helpers来帮助缓解类型推断问题。
在这种情况下,
Singles.zip(..., ...)
将能够毫无歧义地正常工作。请注意,我使用的是Singles
,而不是Single