如何对类型层次结构中包含的类进行算术运算?
我一直在尝试在摘要中存储不同类型的指标,以便我可以计算每个指标集合的聚合。
在下文中,我展示了我的实施尝试:
在我的第一次尝试中,我只使用了一个简单的类层次结构
sealed trait Metric {
def getValue(): Number = ???
}
class Counter(count: Int) extends Metric {
override def getValue() : Int = count
}
class Meter(rate: Double) extends Metric {
override def getValue() : Double = rate
}
class Container(val key: String, x : Metric, val y : Metric) {
// ERROR: Type mismatch expected: String actually: Number
def combine(): Number = x.getValue + y.getValue
}
object Main {
var list : List[Container] = List()
var res : Map[String, Number] = list.map(x => x.key -> x.combine()).toMap
}
我的第二次尝试使用了泛型
sealed trait Metric2[M] {
def getValue(): M = ???
}
class Counter2(count: Int) extends Metric2[Int] {
override def getValue() : Int = count
}
class Meter2(rate: Double) extends Metric2[Double] {
override def getValue() : Double = rate
}
class Container2[T](val key : String, x : Metric2[T], y: Metric2[T]) {
// ERROR: Type mismatch expected: String actually: Number
def combine(): T = x.getValue + y.getValue
}
object Main2 {
var list2 : List[Container2[Number]] = List()
var res : Map[String, Number] = list2.map(x => x.key -> x.combine()).toMap
}
错误在代码中突出显示。
据我所知,Number类实际上不是scala类型层次结构的一部分,而是使用Numeric。也许这是我的代码出错的地方。但是我找不到关于Numeric使用的好教程。任何提示都表示赞赏!
[编辑:]感谢Alexey Romanov的解决方案。我指定了容器的两个版本,一个带有implicts和context,另一个没有。
sealed abstract class Metric[M] {
abstract def value(): M
}
class Counter(count: Int) extends Metric[Int] {
override def value() : Int = count
}
class Meter(rate: Double) extends Metric[Double] {
override def value() : Double = rate
}
class Container[T](val key : String, x : Metric[T], y: Metric[T])(implicit ev: Numeric[T]) {
def combine(): T = implicitly[Numeric[T]].plus(x.value, y.value)
}
class Container2[T: Numeric](val key : String, x : Metric[T], y: Metric[T]) {
import scala.Numeric.Implicits._
def combine(): T = x.value + y.value
}
object Main {
var list : List[Container[Number]] = List()
var res : Map[String, Number] = list.map(x => x.key -> x.combine()).toMap
}
答案 0 :(得分:3)
所需的修补程序非常小:
sealed abstract class Metric2[M: Numeric] {
def getValue(): M
}
// no changes to Counter2 or Meter2
import scala.Numeric.Implicits._
class Container2[T: Numeric](val key : String, x : Metric2[T], y: Metric2[T]) {
def combine(): T = x.getValue + y.getValue
}
: Numeric
语法是context bound,import
用于提供良好的运算符语法(如果没有它,则需要直接调用Numeric
方法)。
作为旁注:
getValue()
应该是抽象的,允许您不实施此默认实施是有害的;
在没有括号的情况下调用value
更好的Scala风格。