我无法扩展扩展Ordered [Base]的基类。我的派生类无法扩展Ordered [Derived],因此不能用作TreeMap中的键。如果我创建一个TreeMap [Base],然后在Derived中覆盖比较,它可以工作,但它不是我想要的。我希望能够将派生类作为关键。有办法解决这个问题吗?
case class A(x: Int) extends Ordered[A] {
def compare(that: A) = x.compare(that.x)
}
// Won't compile
// case class B(val y : Int) extends A(1) with Ordered[B] {
// def compare(that: B) = x.compare(that.x) match {
// case 0 => y.compare(that.y)
// case res => res
// }
// }
// Compiles but can't be used to define a TreeMap key
case class B(y: Int) extends A(1) {
override def compare(that: A) = that match {
case b: B => x.compare(b.x) match {
case 0 => y.compare(b.y)
case res => res
}
case _: A => super.compare(that)
}
}
def main(args: Array[String]) {
TreeMap[B, Int]() // Won't compile
}
修改
scala邮件列表上的This discussion似乎非常相关,但它让我有点失望。
答案 0 :(得分:4)
您可以使用从B到Ordered [B]的类型转换:
class OrderedB(me : B) extends Ordered[B]{
def compare(that: B) = me compare that
}
collection.immutable.TreeMap.empty[B, Int](new OrderedB(_))
我认为B总是A的子类型,这意味着Order [A] A类型是不变的。它不能定义第二个比较方法来实现Order [B],其类型错误与Ordered [A]中的compare方法相同。
或者,您可以定义从B到Ordered [B]的隐式类型版本:
implicit def orderedA2orderedB[B <: A with Ordered[A]](b : B) : Ordered[B] = b.asInstanceOf[Ordered[B]]
collection.immutable.TreeMap[B, Int]()
这应该是有效的。我不知道在没有强制转换的类型系统中表达这种方法的方法。
答案 1 :(得分:3)
特征Ordered
采用参数。一个类型参数,被授予,但它的工作方式与任何其他参数一样。当您将它扩展两次时,在基类和子类中,您不会“导入”两个版本的Ordered
。而是进行类的线性化,并且只导入一次。因此,您无法向其传递两个不同的参数。
现在,TreeMap
不需要subclass
Ordered
的原因,只是从您的班级转换为Ordered
的{{1}}。正是为了使这些事情成为可能。你不应该直接扩展这些东西,而应该暗示它们:
scala> class A(val x: Int)
defined class A
scala> class B(x : Int, val y : Int) extends A(x)
defined class B
scala> import scala.collection.immutable.TreeMap
import scala.collection.immutable.TreeMap
scala> class AOrd(a: A) extends Ordered[A] {
| def compare(that: A) = a.x.compare(that.x)
| }
defined class AOrd
scala> object AOrd {
| implicit def toAOrd(a: A) = new AOrd(a)
| }
defined module AOrd
scala> class BOrd(b: B) extends Ordered[B] {
| def compare(that: B) = b.x.compare(that.x) match {
| case 0 => b.y.compare(that.y)
| case res => res
| }
| }
defined class BOrd
scala> object BOrd {
| implicit def toBOrd(b: B) = new BOrd(b)
| }
defined module BOrd
scala> import AOrd._
import AOrd._
scala> import BOrd._
import BOrd._
scala> TreeMap[B, Int]()
res1: scala.collection.immutable.SortedMap[B,Int] = Map()
答案 2 :(得分:2)
您可以在某处将隐式排序[B]放在范围内,如下所示:
object BOrdering extends Ordering[B] {
def compare(a: B, b: B) = a.compare(b)
}
implicit val bo = BOrdering
TreeMap[B, Int]() // Now it works!
编辑:这只适用于Scala 2.8(谢谢,Ken)