質問

Ordered [Base]を拡張する基本クラスの拡張に問題があります。私の派生クラスはOrdered [Derived]を拡張できないため、TreeMapのキーとして使用できません。 TreeMap [Base]を作成し、Derivedで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から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は常にOrder [A] whoesタイプAが不変であることを意味するAのサブタイプである必要があると思います。 2番目の比較メソッドを定義して、Ordered [A]の比較メソッドと同じタイプのエラーを持つOrder [B]を実装することはできません。

別の方法として、BからOrdered [B]への暗黙的なタイプバージョンを定義できます。

implicit def orderedA2orderedB[B <: A with Ordered[A]](b : B) : Ordered[B] = b.asInstanceOf[Ordered[B]]
collection.immutable.TreeMap[B, Int]()

これは有効でなければなりません。これをキャストなしの型システムで表現する方法を知りません。

他のヒント

特性 Ordered はパラメーターを取ります。許可された型パラメーターですが、他のパラメーターと同様に機能します。基本クラスとサブクラスで2回拡張すると、「インポート」ではなくなります。 Ordered の2つのバージョン。代わりに、クラスの線形化が行われ、一度だけインポートします。そのため、2つの異なるパラメーターを渡すことはできません。

今、 TreeMap Ordered subclass を必要とせず、クラスから >注文済み。まさにそのようなことを可能にすることです。これらのものを直接拡張する代わりに、それらを暗黙的にすべきです:

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()

次のように、暗黙的なOrdering [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)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top