繁体   English   中英

特征val成员与抽象类型的Scala比较

[英]Scala compare of trait val member with abstract type

我试图弄清楚如何使用抽象类型而不是使用类型参数来表达下面的代码。

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:KeyDouble

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

但这也失败了,因为编译器并不认为比较是定义的。 此外,是否有一种解决方案,可以通过限制K(例如, type K <: Ordered[K]compare移入特征密钥?

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

这是一个定义,它将在编译时强制执行约束,并将compare的定义拉入基本成员:

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不是Ordered的子类型,但有可用的隐式转换。

从Key中消除类型参数同时仍然允许安全地排序键的唯一方法是从Key类型定义隐式转换Ordered键类型。 这也使得分析比较方法变得简单。

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.wrap trait / object键入虚拟对象以确保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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM