Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Inheritance 扩展scala扩展有序的类_Inheritance_Scala_Covariance - Fatal编程技术网

Inheritance 扩展scala扩展有序的类

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

扩展扩展有序[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 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)

trait
Ordered
接受一个参数。一个类型参数被授予,但它与任何其他参数一样工作。当您在基类和子类中扩展它两次时,您不是在“导入”两个版本的
已排序。相反,会对类进行线性化,并且只导入一次。因此,不能向其传递两个不同的参数

现在,有一个原因是
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是的。现在,您使用
排序
类型类,而不是扩展
排序