如何在扩展Scala Enumeration.Val时获得正确的值类型



虽然S/O上有很多关于Scala枚举困难的问题,但我还没有找到一个能解决我问题的问题。具体来说,我试图将Planet示例从Oracle Java枚举文档翻译成Scala枚举习语,以便更好地理解其工作原理和pro的&Scala形式的con。

到目前为止,我移植的代码出现在下面,可以说,它并没有像从最不意外的原则中预期的那样编译。除了使用.asInstanceOf进行类型转换外,还有更好或可接受的解决方案吗?

谢谢,Justin

    object Planet extends Enumeration {
  // universal gravitational constant (m3 kg-1 s-2)
  val G = 6.67300E-11
  val Mercury = Planet(3.303e+23, 2.4397e6)
  val Venus = Planet(4.869e+24, 6.0518e6)
  val Earth = Planet(5.976e+24, 6.37814e6)
  val Mars = Planet(6.421e+23, 3.3972e6)
  val Jupiter = Planet(1.9e+27, 7.1492e7)
  val Saturn = Planet(5.688e+26, 6.0268e7)
  val Uranus = Planet(8.686e+25, 2.5559e7)
  val Neptune = Planet(1.024e+26, 2.4746e7)
  case class Planet(mass: Double, radius: Double) extends Val {
    def surfaceGravity: Double = G * mass / (radius * radius)
    def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
  }
}
object PlayEnumeration extends App {

  val earthWeight = 175
  val mass = earthWeight / Planet.Earth.surfaceGravity
  Planet.values.foreach {
    // Does not compile as might be expected.
    // value surfaceWeight is not a member of play.Planet.Value
    p => println(s"Your weight on $p is ${p.surfaceWeight(mass)}")
  }
  println
}

尝试使用asInstanceOf[Planet]将枚举值强制转换为Planet

object PlanetEnum extends Enumeration {
  // universal gravitational constant (m3 kg-1 s-2)
  val G = 6.67300E-11
  val Mercury = Planet(3.303e+23, 2.4397e6)
  val Venus = Planet(4.869e+24, 6.0518e6)
  val Earth = Planet(5.976e+24, 6.37814e6)
  val Mars = Planet(6.421e+23, 3.3972e6)
  val Jupiter = Planet(1.9e+27, 7.1492e7)
  val Saturn = Planet(5.688e+26, 6.0268e7)
  val Uranus = Planet(8.686e+25, 2.5559e7)
  val Neptune = Planet(1.024e+26, 2.4746e7)
  case class Planet(mass: Double, radius: Double) extends Val {
    def surfaceGravity: Double = G * mass / (radius * radius)
    def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
  }
}
object PlayEnumeration extends App {
  val earthWeight = 175
  val mass = earthWeight / PlanetEnum.Earth.surfaceGravity
  PlanetEnum.values.foreach {
    p => println(s"Your weight on $p is ${p.asInstanceOf[Planet].surfaceWeight(mass)}")
  }
  println
}

将以下行添加到object Planet

implicit def convert(value: Value): Planet = value.asInstanceOf[Planet]

这充分利用了Scala中隐含者的非凡能力。

如果你正在寻找能给你带来更多灵活性的东西(尤其是详尽的模式匹配),我刚刚发布了一个答案,展示了我在Scala中枚举的通用解决方案。

在对选项进行了广泛的研究后,该解决方案对该领域进行了更全面的概述,包括解决"密封特征+事例对象"模式,我最终解决了JVM类/对象初始化排序问题。

最新更新