Kotlin构造函数引用泛型

Sta*_*viv 6 kotlin rx-java2

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

Observable.fromArray(1, 2, 3)
    .flatMap(this::intToBooleanObservable, Pair::new)
    .....
Run Code Online (Sandbox Code Playgroud)

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

Observable.fromArray(1, 2, 3)
    .flatMap(::intToBooleanObservable, ::Pair)
    .....
Run Code Online (Sandbox Code Playgroud)

但是编译器无法推断出Pair的泛型类型,所以我现在能做的最好的事情是:

.flatMap(::intToBooleanObservable, { a, b -> a to b })
Run Code Online (Sandbox Code Playgroud)

这并不像我希望的那样简洁.

有没有办法实现这个不声明变量ab

Geo*_*izy 2

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

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 } }
}
Run Code Online (Sandbox Code Playgroud)

2) 将包装移至条件 Observable(此处为 intToBooleanObservable),以 Pair 或更明确的自定义类型返回结果(具有 2 个子级的密封类,如 Success 和 Failure)。这使得代码更加明确:

 when(it) {
   is Success -> ...
   is Failure -> ...
}
Run Code Online (Sandbox Code Playgroud)

3)根据 intToBooleanObservable 结果,你现在有 2 个不同的场景(我想)。通常,这是一种失败/否认,可以快速解决。对于这个问题,编写一个具有副作用的过滤器,其中谓词是一个 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
Run Code Online (Sandbox Code Playgroud)

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

希望它能有所帮助。