加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala类型边界和Java通用互操作

发布时间:2020-12-16 09:57:52 所属栏目:安全 来源:网络整理
导读:我试图包装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 thisJa
我试图包装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会使这一切变得更容易,但也许有充分的理由说明为什么不是这样...... [*]更像是“但我怀疑”

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读