Ale*_*rek 4 java lambda kotlin method-reference rx-java2
我有一个示例Java代码使用方法引用,我想重写为Kotlin.Java版本使用方法参考,解决方案简短明了.但另一方面,我不能在Kotlin中使用方法参考.我设法编写的唯一版本如下所示.似乎Function3 { s: String, b: Boolean, i: Int -> combine(s, b, i) }可以用更干净的方式编写(如果可能的方法参考将是完美的).
我是Kotlin的新手,所以我会感激任何线索.
Java的
import io.reactivex.Observable;
public class TestJava {
Observable<String> strings() {
return Observable.just("test");
}
Observable<Boolean> booleans() {
return Observable.just(true);
}
Observable<Integer> integers() {
return Observable.just(1);
}
void test() {
Observable.combineLatest(strings(), booleans(), integers(),
this::combine);
}
double combine(String s, boolean b, int i) {
return 1.0;
}
}
Run Code Online (Sandbox Code Playgroud)
科特林
import io.reactivex.Observable
import io.reactivex.functions.Function3
class TestKotlin {
fun strings(): Observable<String> {
return Observable.just("test")
}
fun booleans(): Observable<Boolean> {
return Observable.just(true)
}
fun integers(): Observable<Int> {
return Observable.just(1)
}
fun test() {
Observable.combineLatest(strings(), booleans(), integers(),
Function3 { s: String, b: Boolean, i: Int -> combine(s, b, i) })
}
fun combine(s: String, b: Boolean, i: Int): Double {
return 1.0
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
以下Kotlin中的方法引用给出了错误.
fun test() {
Observable.combineLatest(strings(), booleans(), integers(), this::combine)
}
fun test() {
Observable.combineLatest(strings(), booleans(), integers(), TestKotlin::combine)
}
Run Code Online (Sandbox Code Playgroud)
使用提供的参数不能调用以下任何函数:@CheckReturnValue @SchedulerSupport public final fun combineLatest(p0:((Observer) - > Unit)!,p1:((Observer) - > Unit)!,p2:((观察者) - >单位)!,p3:((???,???,???) - > ???)!):可观察<(??? ???)>!在io.reactivex.Observable中定义@CheckReturnValue @SchedulerSupport public open fun combineLatest(p0:ObservableSource!,p1:ObservableSource!,p2:ObservableSource!,p3:io.reactivex.functions.Function3!):Observable <(???. ???)>!在io.reactivex.Observable中定义@CheckReturnValue @SchedulerSupport public open fun combineLatest(p0:Function!,out(??? .. ???)>!,p1:Int,vararg p2:ObservableSource!):Observable <(? ?? .. ???)>!在io.reactivex.Observable中定义
编辑2
RxKotlin解决了答案中提到的问题.
import io.reactivex.rxkotlin.Observables
class TestKotlin {
fun test() {
Observables.combineLatest(strings(), booleans(), integers(), this::combine)
}
}
Run Code Online (Sandbox Code Playgroud)
您也可以在Kotlin中使用函数引用表达式,就像Java中的方法引用表达式一样.例如,Kotlin中的combine函数引用KFunction3如下:
val f: kotlin.reflect.KFunction3<String, Boolean, Int, Double> = this::combine
Run Code Online (Sandbox Code Playgroud)
在java中,方法引用表达式可以分配给任何兼容的 功能接口,但是您不能将功能引用表达式分配给任何功能类型,即使它们是兼容的,例如:
val f:io.reactivex.functions.Function3<String,Boolean,Int,Double> =this::combine
// type mismatch error ---^
Run Code Online (Sandbox Code Playgroud)
实际上,Kotlin使用SAM转换将lambda/Function Reference Expression转换为Java Functional Interface的实现,这意味着Kotlin执行如下操作:
fun test() = TODO()
val exector:Executor = TODO()
exector.execute(::test)
//::test compile to java code as below:
Runnable task = new Runnable(){
public void run(){
test();
}
};
Run Code Online (Sandbox Code Playgroud)
为什么方法参考表达式在Java中可以正常工作,但在Kotlin中使用函数参考表达式失败了?
基于上面的内容,您可以看到rx-java2中有许多重载combineLatest方法.例如,以下两个不能正确使用函数引用表达式 Kotlin :
combineLatest(
ObservableSource<out T1>,
ObservableSource<out T2>,
ObservableSource<out T3>,
Function3<T1, T2, T3, out R>
)
combineLatest(
ObservableSource<out T1>,
ObservableSource<out T2>,
ObservableSource<out T3>,
ObservableSource<out T4>,
Function4<T1, T2, T3, T4, out R>
)
Run Code Online (Sandbox Code Playgroud)
正如我所说,Kotlin使用SAM转换将lambda/函数引用表达式转换为Java 功能接口,但它不能直接分配给Java 功能接口.
combineLatestKotlin中方法的第4个参数,编译器根本无法推断其类型,因为第4个参数类型可以是io.reactivex.functions.Function3或ObservableSource.因为ObservableSource它也是一个Java 功能接口.
当您遇到SAM转换冲突时,您可以使用将lambda转换为特定SAM类型的适配器函数,例如:
typealias RxFunction3<T1, T2, T3, R> = io.reactivex.functions.Function3<T1,T2,T3,R>
val f: RxFunction3<String, Boolean, Int, Double> = RxFunction3{ s, b, i-> 1.0}
Run Code Online (Sandbox Code Playgroud)
因此,在使用lambda/Function Reference Expression之前必须使用自适应,例如:
typealias RxFunction3<T1, T2, T3, R> = io.reactivex.functions.Function3<T1,T2,T3,R>
fun <T1,T2,T3,R> KFunction3<T1,T2,T3,R>.toFunction3(): RxFunction3<T1, T2,T3,R> {
return RxFunction3 { t1, t2, t3 -> invoke(t1, t2, t3) }
}
Run Code Online (Sandbox Code Playgroud)
然后您可以使用下面的函数引用表达式,例如:
Observable.combineLatest(
strings(),
booleans(),
integers(),
// v--- convert KFunction3 to RxFunction3 explicitly
this::combine.toFunction3()
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1863 次 |
| 最近记录: |