繁体   English   中英

类层次结构上的算法

[英]Arithmetics on a class hierarchy

如何对类型层次结构中包含的类进行算术运算?

我一直在尝试在摘要中存储不同类型的指标,以便可以在每个指标集合上计算聚合。

下面,我展示了我的实现尝试:
在我的第一次尝试中,我仅使用了简单的类层次结构

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。 也许这是我的代码转错了地方。 但是我找不到关于数字用法的很好的教程。 任何提示表示赞赏!

[编辑:]感谢Alexey Romanov的解决方案。 我指定了容器的两个版本,一个带有隐式和上下文,另一个没有。

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
}

所需的修复很小:

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语法是上下文绑定的 ,并且import用于提供不错的运算符语法(如果没有,则需要直接调用Numeric方法)。

附带说明:

  1. getValue()应该是抽象的,此默认实现会因不允许您不实现而对它有害。

  2. 最好使用Scala样式来将其命名为不带括号的value

暂无
暂无

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

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