斯卡拉特质VAL成员的比较抽象类型

问题描述:

即时试图找出如何使用抽象类,而不是使用类型参数来表达下面的代码。斯卡拉特质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

,以消除重点,同时仍允许密钥安全地订购的类型参数的唯一方法是定义从主要类型的有序密钥类型的隐式转换。这也使得比较方法的分解变得简单。

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) 

我认为你需要至少一种类型的参数来表示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