문제

주문한 [기본]을 확장하는 기본 클래스를 연장하는 데 어려움이 있습니다. 내 파생 클래스는 순서대로 확장 할 수 없으므로 Treemap에서 열쇠로 사용할 수 없습니다. 트리 맵 [베이스]을 만들고 그 파생에서 비교를 무시하면 내가 원하는 것이 아닙니다. 나는 파생 수업을 열쇠로 가질 수 있기를 원합니다. 이것에 대한 방법이 있습니까?

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
}

편집하다

이 토론 스칼라 메일 링리스트에서는 매우 관련성이있는 것처럼 보이지만 약간 잃어 버립니다.

도움이 되었습니까?

해결책

b에서 순서대로 유형 변환을 사용할 수 있습니다 [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의 하위 유형이어야한다고 생각한다. 순서 대상 [a]의 비교 메소드와 동일한 유형의 오류로 순서 [b]를 구현하기 위해 두 번째 비교 방법을 정의 할 수 없습니다.

또는 b에서 순서로 내재 된 [b]까지 암시 적 유형 버전을 정의 할 수 있습니다.

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

이것은 유효해야합니다. 나는 캐스트없이 유형 시스템에서 이것을 표현하는 방법을 모릅니다.

다른 팁

특성 Ordered 매개 변수를 가져옵니다. 유형 매개 변수는 부여되었지만 다른 매개 변수와 마찬가지로 작동합니다. 기본 클래스와 서브 클래스에서 두 번 확장하면 두 버전을 "가져 오기"하지 않습니다. Ordered. 대신, 클래스의 선형화가 이루어지고 한 번만 가져옵니다. 이러한 이유로 두 가지 매개 변수를 전달할 수 없습니다.

이제 이유가 있습니다 TreeMap 필요하지 않습니다 subclassOrdered, 단지 수업에서 An 로의 전환 Ordered 그것의. 그러한 것들을 가능하게하는 것은 정확히 있습니다. 이러한 것들을 직접 확장하는 대신 다음을 암시해야합니다.

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

다음과 같이 암시 적 순서 [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