使用泛型的 Kotlin 构造函数参考
Kotlin constructor reference with generics
我在 (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 })
这并不像我希望的那样简洁。
有没有办法在不声明变量 a
和 b
的情况下实现这一点?
同样的问题。其他一些解决方法(按照我使用它们的顺序),您可能会喜欢其中之一。
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 或更明确的自定义类型(密封 class 与 2 个孩子,如成功和失败)返回。这会启用更明确的代码:
when(it) {
is Success -> ...
is Failure -> ...
}
3) 根据 intToBooleanObservable 结果,您现在有 2 种不同的场景(我想)。通常一个是一种failure/denial,快速解决。为此,编写一个具有副作用的过滤器,其中谓词是一个 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) 最后一种方法仅适用于布尔结果。如果我对 failure/refusal 背后的原因感兴趣并给出有意义的信息怎么办?为了同构代码,我放弃了这个运算符。受其他函数式语言的启发,我定义了一个 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)
}
}
}
希望对您有所帮助。
我在 (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 })
这并不像我希望的那样简洁。
有没有办法在不声明变量 a
和 b
的情况下实现这一点?
同样的问题。其他一些解决方法(按照我使用它们的顺序),您可能会喜欢其中之一。
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 或更明确的自定义类型(密封 class 与 2 个孩子,如成功和失败)返回。这会启用更明确的代码:
when(it) {
is Success -> ...
is Failure -> ...
}
3) 根据 intToBooleanObservable 结果,您现在有 2 种不同的场景(我想)。通常一个是一种failure/denial,快速解决。为此,编写一个具有副作用的过滤器,其中谓词是一个 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) 最后一种方法仅适用于布尔结果。如果我对 failure/refusal 背后的原因感兴趣并给出有意义的信息怎么办?为了同构代码,我放弃了这个运算符。受其他函数式语言的启发,我定义了一个 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)
}
}
}
希望对您有所帮助。