我想使用Scala中的Guavas Range。但是,它希望元素实现Comparable
接口。所以我不能简单地使用
val range = Range.open(4, 5)
因为Int
未实现Comparable
或Ordered
。但是有一个Ordering[Int]
类型的类。我到目前为止唯一的想法是使用视图边界
def open[T](from:T, to:T)(implicit ord: T => Ordered[T]) = Range.open(ord(from), ord(to))
但是我得到了一个CCE:
val range = open(4,5) //> java.lang.ClassCastException: scala.runtime.RichInt cannot be cast to java.l
//| ang.Integer
//| at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:106)
//| at scala.math.Ordering$Int$.compare(Ordering.scala:256)
//| at scala.runtime.OrderedProxy$class.compare(ScalaNumberProxy.scala:71)
//| at scala.runtime.RichInt.compare(RichInt.scala:15)
//| at scala.math.Ordered$class.compareTo(Ordered.scala:91)
//| at scala.runtime.RichInt.compareTo(RichInt.scala:15)
//| at com.google.common.collect.Range.compareOrThrow(Range.java:711)
//| at com.google.common.collect.Cut.compareTo(Cut.java:75)
//| at com.google.common.collect.Range.<init>(Range.java:364)
//| at com.google.common.collect.Range.create(Range.java:156)
//| at com.google.common.collect.Range.open(Range.java:168)
为什么会导致ClassCastException?
有更好的方法吗?注意:使用Int
只是一个最小的例子。我有更复杂的类型,它们没有实现Ordered
但在范围内有Ordering
。
答案 0 :(得分:4)
只需明确指定您要封装到java.lang.Integer
:
import java.lang.{Integer => jI}
Range.open[jI](3,5)
如果您不喜欢在每次通话时都这样做,请按照建议打包电话。
答案 1 :(得分:2)
您获得了CCE,因为RichInt
未实现Ordered[RichInt]
,但Ordered[Int]
。
我建议你自己包装它类似于
case class AsOrdered[T](val value: T)(implicit ord: Ordering[T]) extends Ordered[AsOrdered[T]] {
override def compare(that: AsOrdered[T]) = ord.compare(value, that.value)
}
def open[T: Ordering](from: T, to: T) = {
val ord = implicitly[Ordering[T]]
Range.open(AsOrdered(from), AsOrdered(to))
}
您需要提供额外的逻辑来提取值,因为您不会获得Range[Int]
而是Range[AsOrdered[Int]]
修改强>