Kotlin构造函数参考泛型

我在(Rx)Java中有这样的代码:

Observable.fromArray(1, 2, 3) .flatMap(this::intToBooleanObservable, Pair::new) ..... 

我期望相应的Kotlin代码看起来像:

 Observable.fromArray(1, 2, 3) .flatMap(::intToBooleanObservable, ::Pair) ..... 

然而,编译器不能推断Pair的通用类型,所以我现在可以做的最好的是:

 .flatMap(::intToBooleanObservable, { a, b -> a to b }) 

这不像我希望的那样简洁。

有没有办法实现这一点,而不宣布变量ab

这里同样麻烦。 其他一些解决方法(按照我使用的顺序),您可能会喜欢其中的一种。

1)编写自己的操作员:

 fun <T, U> Single<T>.flatMapPair(func: (T) -> Single<U>) : Single<Pair<T, U>> { return this.flatMap { t -> func.invoke(t).map { u -> t to u } } } 

2)将包装移动到有条件的Observable(这里是intToBooleanObservable),将结果作为Pair或更明确的自定义类型(带有2个孩子的密封类,如成功和失败)返回。 这使得更明确的代码:

  when(it) { is Success -> ... is Failure -> ... } 

3)根据intToBooleanObservable的结果,你现在有2个不同的场景(我想象)。 通常情况下,这是一种失败/拒绝,很快就可以解决。 对于这个问题,在predicate是Observable的地方写一个带有副作用的过滤器,从而避免这个问题:

 fun <T> Observable<T>.filterSingle(predicate: (T) -> Single<Boolean>, rejectionFunction: (T) -> Unit): Observable<T> = ... //filter with the given predicate, and call rejectionFunction if item doesn't pass 

4)最后一种方法只适用于布尔结果。 如果我对失败/拒绝给出有意义的信息背后的原因感兴趣呢? 为了均匀的代码,我放弃了这个操作符。 受其他功能语言的启发,我定义了一个Either类型并定义了泛型Either + RxJava操作符; mapRight,flatMapRight和更重要的dropLeft。 dropLeft就像filterSingle的泛化一样。

 inline fun <L, R> Observable<Either<L, R>>.dropLeft(crossinline sideEffect: (L) -> Unit): Observable<R> = this.lift { downObserver -> object: Observer<Either<L, R>> { override fun onError(throwable: Throwable?) = downObserver.onError(throwable) override fun onSubscribe(disposable: Disposable?) = downObserver.onSubscribe(disposable) override fun onComplete() = downObserver.onComplete() override fun onNext(either: Either<L, R>) = when (either) { is Right -> downObserver.onNext(either.value) is Left -> sideEffect(either.value) } } } 

希望它可以帮助。