在值类中抽象出函数

时间:2017-11-05 23:22:58

标签: scala

假设我有值类的以下代码:

class Meters(val x: Int) extends AnyVal {
  def +(m: Meters): Meters = new Meters(x + m.x)
}

class Seconds(val x: Int) extends AnyVal {
  def +(s: Seconds): Seconds = new Seconds(x + s.x)
}

有什么方法可以删除“+”方法的重复吗? 有点像:

abstract class Units[T <: Units[T]](val x: Int) extends AnyVal {
  def +(other: T): T = T(x + other.x)
}

除非我不能从值类继承,否则我绝对不能像构造函数一样使用T

1 个答案:

答案 0 :(得分:2)

您可以将universal trait与类型类一起使用,让我们开始定义特征。

trait Sum[T <: Sum[T]] extends Any {
  val x: Int
  def +(other: T)(implicit evidence : FromInt[T]): T = evidence.fromInt(x + other.x)
}

现在我们需要一个类型类来告诉我们如何从一个整数变为某种类型,让我们定义它并调用它FromInt

 trait FromInt[T] {
  def fromInt(x: Int) : T
}

现在让我们定义一个简单的Meters值类     class Meters(val x :Int) extends AnyVal with Sum[Meters] 在伴随对象中,我们可以提供我们定义的类型类的隐式值。

object Meters{
  implicit val intConstructable : FromInt[Meters] = new FromInt[Meters] {
  override def fromInt(x: Int) = new Meters(x)
}
}

现在我们可以做到

val added = new Meters(2) + new Meters(3)
println(added.x)