순서를 확장하는 스칼라 클래스를 확장합니다
-
10-07-2019 - |
문제
주문한 [기본]을 확장하는 기본 클래스를 연장하는 데 어려움이 있습니다. 내 파생 클래스는 순서대로 확장 할 수 없으므로 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
필요하지 않습니다 subclass
의 Ordered
, 단지 수업에서 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)