2011-01-05 162 views
3

即時試圖找出如何使用抽象類,而不是使用類型參數來表達下面的代碼。斯卡拉特質VAL成員的比較抽象類型

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 
} 

我目前的版本看起來如下:

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]。使用抽象類型有什麼更好/其他方法來實現抽象成員的排序?

我也試圖確保that:Key類型是Double

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

但由於犯規覺得比較定義編譯器,這也將失敗。此外,是否有解決方案compare可以通過限制K(例如type K <: Ordered[K])轉移到特徵密鑰?

+0

完全避免這裏有序,並提供一個隱含的對象,參與排序[DoubleKey]。這使事情變得更容易... – Landei 2011-01-05 15:01:27

回答

1

,以消除重點,同時仍允許密鑰安全地訂購的類型參數的唯一方法是定義從主要類型的有序密鑰類型的隱式轉換。這也使得比較方法的分解變得簡單。

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會話(特別注意:包裝特質/對象鍵在虛擬對象,以確保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

我認爲你需要至少一種類型的參數來表示DoubleKeyStringKey沒有可比性。這是沒有意義的寫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 

這裏是將強制約束在編譯的時候,也拉動比較的定義的定義到基部構件:

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 

注意,我使用的結合的圖,作爲DoubleString不亞型有序,但也有隱式轉換。

+0

感謝您的回答!它比「接受」更簡潔。 – Malcolm 2014-04-20 00:43:21