Inheritance 扩展scala扩展有序的类
扩展扩展有序[base]的基类时遇到问题。我的派生类无法扩展Ordered[Derivated],因此不能用作树映射中的键。如果我创建一个树形图[Base],然后在派生中覆盖compare,这是可行的,但这不是我想要的。我希望能够将派生类作为键。有办法解决这个问题吗Inheritance 扩展scala扩展有序的类,inheritance,scala,covariance,Inheritance,Scala,Covariance,扩展扩展有序[base]的基类时遇到问题。我的派生类无法扩展Ordered[Derivated],因此不能用作树映射中的键。如果我创建一个树形图[Base],然后在派生中覆盖compare,这是可行的,但这不是我想要的。我希望能够将派生类作为键。有办法解决这个问题吗 case class A(x: Int) extends Ordered[A] { def compare(that: A) = x.compare(that.x) } // Won't compile // case cl
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邮件列表上的内容似乎非常相关,但我有点不知所措。您可以使用从B到有序[B]的类型转换:
class OrderedB(me : B) extends Ordered[B]{
def compare(that: B) = me compare that
}
collection.immutable.TreeMap.empty[B, Int](new OrderedB(_))
implicit def orderedA2orderedB[B <: A with Ordered[A]](b : B) : Ordered[B] = b.asInstanceOf[Ordered[B]]
collection.immutable.TreeMap[B, Int]()
我认为B总是a的一个子类型,这意味着a的类型是不变的。它无法定义第二个比较方法来实现Order[B],该方法的类型与Ordered[a]中的比较方法的类型相同
或者,您可以定义从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(_))
implicit def orderedA2orderedB[B <: A with Ordered[A]](b : B) : Ordered[B] = b.asInstanceOf[Ordered[B]]
collection.immutable.TreeMap[B, Int]()
implicit def orderedA2orderedB[B您可以将隐式排序[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)traitOrdered
接受一个参数。一个类型参数被授予,但它与任何其他参数一样工作。当您在基类和子类中扩展它两次时,您不是在“导入”两个版本的
已排序。相反,会对类进行线性化,并且只导入一次。因此,不能向其传递两个不同的参数
现在,有一个原因是TreeMap
不需要的子类,只需要将类转换为有序的。这正是使这些事情成为可能的。与其直接扩展这些事情,不如为它们隐含:
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()
谢谢你的帮助,托马斯。我希望可能有一些我错过的Scala魔法可以让它发挥作用。而不必求助于本质上传递一个比较器。这只是我,还是这看起来很有限,很烦人?或者这只是在使用Ordered[T]时所期望的,您通常应该使用@Dave-我添加了一个隐式类型转换版本。它并不完美,因为需要强制转换。@Ken-您可以添加一个答案吗?我不知道视图绑定在哪里。@Thomas-谢谢您的回答。强制转换并不漂亮,但效果很好,通过将转换放在B的伴生对象中,就可以了使用它的人甚至看不见。这正是我想要的。你如何支持A和B的自然排序?总是导入AOrd。&BOrd。&Ud。不好,每个a1:A$scala
@Thomas:esult生成两个新的AOrd实例,除非JIT优化新实例,否则将立即对其进行垃圾收集。Scala总是会出现短期对象,JVM非常擅长对其进行优化。另外,您可以在A上定义方法,在B上重写,而无需扩展顺序(不过,您仍然需要AOrd和BOrd进行排序)。不幸的是,Ordered并不是反向变量,这使得无法使用A的排序来对B进行排序。@qertoip是的。现在,您使用排序
类型类,而不是扩展排序
。