Scala类型边界和Java通用互操作
我试图包装rx
java的超时
method以使其可用
for scala.
与many other methods类似,我试过这个: def timeout[U >: T](timeout: Duration,other: Observable[U]): Observable[U] = { val otherJava: rx.Observable[_ <: U] = other.asJavaObservable val thisJava: rx.Observable[_ <: U] = this.asJavaObservable toScalaObservable[U](thisJava.timeout(timeout.length,timeout.unit,otherJava)) } 但是我收到以下错误: Observable.scala:1631: error: overloaded method value timeout with alternatives: ($1: Long,x$2: java.util.concurrent.TimeUnit,x$3: rx.Scheduler)rx.Observable[_$85] <and> ($1: Long,x$3: rx.Observable[_ <: _$85])rx.Observable[_$85] cannot be applied to (Long,scala.concurrent.duration.TimeUnit,rx.Observable[_$84]) toScalaObservable[U](thisJava.timeout(timeout.length,otherJava)) 原始的java方法: public Observable<T> timeout(long timeout,TimeUnit timeUnit,Observable<? extends T> other) { return create(OperationTimeout.timeout(this,timeout,timeUnit,other)); } 我对Java和Scala(以及所有类型边界)都不是很熟悉,但据我所知:otherJava和thisJava都是rx.Observable [U]类型,为什么它们不排队? 解决方法
嗯,你正在踩踏Scala中使用的Java泛型的方差问题.我们一步一步走吧.
我们来看看你的实现: // does not compile (with your original error) def timeout[U >: T](timeout: Duration,otherJava)) } 要理解为什么这不起作用,让我们在thisJava的声明中调用A未命名的类型(A<:U,这样thisJava是一个rx.Observable [A]). thisJava的超时方法:rx.Observable [A]需要一个类型为rx.Observable [_<:A]的参数,并给它一个rx.Observable类型[_<:U]:编译器没有知道这两种类型如何相关的方法.它们可能根本不相关! 另一方面,如果A是U,那么thisJava将是一个rx.Observable [U],并且它的超时方法会期望一个rx.Observable [_<:U],它恰好是otherJava的类型.我们试试吧: // still does not compile,sadly def timeout[U >: T](timeout: Duration,other: Observable[U]): Observable[U] = { val otherJava: rx.Observable[_ <: U] = other.asJavaObservable val thisJava: rx.Observable[U] = this.asJavaObservable // variance error toScalaObservable[U](thisJava.timeout(timeout.length,otherJava)) } 在一个完美的世界中,上述方法将起作用.但是,java rx.Observable未定义为协变,因为java中没有定义 – 站点方差注释.所以Scala认为它是不变的. 因此就Scala而言,rx.Observable [_<:U]不是rx.Observable [U],遗憾的是this.asJavaObservable返回一个rx.Observable [_<:U]. 但我们知道[*] rx.Observable< T>应该是协变的,所以我们可以盲目抛弃: // this compiles and *should* work def timeout[U >: T](timeout: Duration,other: Observable[U]): Observable[U] = { val otherJava: rx.Observable[_ <: U] = other.asJavaObservable val thisJava = this.asJavaObservable.asInstanceOf[rx.Observable[U]] toScalaObservable[U](thisJava.timeout(timeout.length,otherJava)) } 这个故事的寓意是,混合Scala的方差和Java的方差总是会让你在这里和那里花费一些时间,必须仔细考虑. 另外,使asJavaObservable返回一个rx.Observable [T]而不是_<:T会使这一切变得更容易,但也许有充分的理由说明为什么不是这样...... [*]更像是“但我怀疑” (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |