2011-01-05 5 views
3

의 스칼라 비교 형식 매개 변수를 사용하는 대신 추상 형식을 사용하여 아래 코드를 표현하는 방법을 알아 내려고합니다.특성 형 요소와 추상 형

trait Key extends Ordered[Key] { 
    type K 
    val key:K 
} 

case class DoubleKey(val key:Double) extends Key { 
    type K = Double 
    def compare(that:Key):Int = this.key compare that.key.asInstanceOf[K] 
} 

을하지만이 유형의 K에 명시 적으로 캐스팅 행복하지 않다 : that.key.asInstanceOf[K] 다음과 같이

trait Key[T] extends Ordered[Key[T]] { 
    val key:T 
} 

case class DoubleKey(key:Double) extends Key[Double] { 
    def compare(that:Key[Double]):Int = this.key compare that.key 
} 

나의 현재 버전은 보인다. 추상적 유형을 사용하여 추상 멤버에 대한 주문을 수행하는 것이 더 좋고/다른 방법이 있습니까?

는 또한 that:Key의 유형이 Double 있는지 확인하기 위해 노력했다 :

def compare(that:Key { type K = Double }):Int = this.key compare that.key

하지만이 또한 정의 비교 생각 나던 컴파일러 때문에 실패합니다. 또한, compare이 K를 제한하여 특성 키로 이동할 수있는 솔루션이 있습니까 (예 : type K <: Ordered[K])?

+0

내가 좋을 것 완전히 여기에 발주하고,에 방지하는 방법 Ordering [DoubleKey]를 수반하는 암시 적 객체를 제공합니다. 그게 훨씬 더 쉽게 ... – Landei

답변

1

키에서 형식 매개 변수를 제거하고 키를 안전하게 정렬 할 수있는 유일한 방법은 키 형식 인 정렬 된 키 형식에서 암시 적 변환을 정의하는 것입니다. 이것은 또한 compare 메소드를 인수 분해하는 것을 간단하게 만든다.

trait Key { type K ; val key : K } 

object Key { 
    type PKey[KK] = Key { type K = KK } 
    implicit def keyIsOrdered[K <% Ordered[K]](lhs : PKey[K]) = new Ordered[PKey[K]] { 
    def compare(rhs : PKey[K]) = lhs.key compare rhs.key 
    } 
} 

case class DoubleKey(val key : Double) extends Key { type K = Double } 
case class StringKey(val key : String) extends Key { type K = String } 

샘플 REPL 세션 (NB. REPL이 동반자로 본다 보장하기 위해 더미 개체의 특성/객체 키 랩),

scala> DoubleKey(23) < DoubleKey(34) 
res3: Boolean = true 

scala> StringKey("foo") < StringKey("bar") 
res4: Boolean = false 

scala> StringKey("foo") < DoubleKey(23) 
<console>:14: error: could not find implicit value for parameter ord: scala.math.Ordering[ScalaObject] 
     StringKey("foo") < DoubleKey(23) 
4

DoubleKey을 말하고 적어도 StringKey이라고 말하는 것은 적어도 하나의 유형 매개 변수가 필요하다고 생각합니다. 이 의미는 클래스 캐스트 예외가 얻을 수있는 현재의 디자인으로 DoubleKey(1.0) < StringKey("foo")

를 작성하지 것이다 : 여기

case class StringKey(val key:String) extends Key { 
    type K = String 
    def compare(that:Key):Int = this.key compare that.key.asInstanceOf[K] 
} 

StringKey("b") < DoubleKey(1.0) // ClassCastException 

를 컴파일 시간에 제약 조건을 적용하고 또한 비교의 정의를 끌어 정의입니다 베이스 부재에 : 나는 Double 또는 String으로, 바인딩 된 뷰를 사용

abstract class Key[K <% Ordered[K]] extends Ordered[Key[K]] { 
    val key:K 
    def compare(that:Key[K]): Int = key compare that.key 
} 

case class DoubleKey(key:Double) extends Key[Double] 
case class StringKey(key:String) extends Key[String] 

StringKey("b") < DoubleKey(1.0) // won't compile 

주의의 아류가 아닌 순서가 있지만 사용할 수 암시 적 변환이 있습니다.

+0

이 답변을 주셔서 감사합니다! 그것은 "받아 들인"것보다 간결합니다. – Malcolm