运行以下代码时,我得到了一些奇怪的结果:
object Example {
implicit object StringOrdering extends Ordering[String] {
def compare(o1: String, o2: String) = {
o1.length - o2.length
}
}
object StringOrdering1 extends Ordering[String] {
def compare(o1: String, o2: String) = {
o2.length - o1.length
}
}
import collection.mutable
import collection.immutable.TreeSet
val x = TreeSet(1, 5, 8, 12)
val y = mutable.Set.empty ++= x // mutable.Set[Int]
val y1 = mutable.Set.empty[Int] ++= x // mutable.Set[Int]
val z = TreeSet.empty ++ y // Set[Any]
val z1 = TreeSet.empty[Int] ++ y // TreeSet[Int]
}
为什么可变和不可变集中的类型推断的行为如此不同?该z
部分最令人困惑,为什么我们至少没有得到一个TreeSet[Any]
?
该问题可以简化为以下形式:
scala> TreeSet.empty[Int] ++ TreeSet.empty[BigInt]
res15: scala.collection.immutable.Set[Any] = Set()
您对的使用TreeSet.empty
不会显示其实际类型。实际上,它甚至不能按原样编译。我正在假设Ordering[A]
您在未显示的范围内有一些隐含的地方where A != Int
。
关于这个问题:
为什么我们至少没有得到TreeSet [Any]
简单的答案是,你不能有一个TreeSet[Any]
没有Ordering[Any]
。如果我尝试将aTreeSet[Int]
与a结合使用TreeSet[BigInt]
,则它们最常见的类型是Any
。ATreeSet
是的一种SortedSet
,但是我们如何排序一组Any
呢?默认情况下,我们不能这样做,因为对一组进行排序实际上没有任何意义Any
。
Ordering[Any]
如果我真的想要的话,我可以设计一个,最后我会得到一个TreeSet[Any]
:
implicit val ordAny = new Ordering[Any] {
def compare(x: Any, y: Any): Int = Ordering.Int.compare(x.hashCode, y.hashCode)
}
scala> TreeSet.empty[Int] ++ TreeSet.empty[BigInt]
res8: scala.collection.immutable.TreeSet[Any] = TreeSet()
但这并没有任何意义。
技术上的答案是,为了连接两个TreeSet
,TreeSet[A]
并且TreeSet[B]
,我们需要一个隐式CanBuildFrom[TreeSet[A], B, TreeSet[B]]
。
有一些 CanBuildFrom
S按产生的SortedSetFactory
,但通知他们如何需要一个隐式Ordering[A]
。由于Ordering[Any]
找不到,因此编译器会寻找更通用的东西,并找到Set[Any]
。这是有道理的,因为如果我们将元素放入不知道如何排序的排序集中,那么我们将不再具有排序集。剩下的只是一个平原Set
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句