【问题标题】:Scala: generic parser for Enumeration valuesScala:枚举值的通用解析器
【发布时间】:2015-09-22 07:45:53
【问题描述】:

我认为应该可以编写一个适用于所有枚举值的通用函数。我先尝试了一个简单的解析器,但失败了:

object Weekday extends Enumeration {
  type Weekday = Value

  val MONDAY = Value("MONDAY")
  val OTHER = Value("OTHER")

  implicit def valueToWeekday(v: Value): Weekday = v.asInstanceOf[Weekday]
  implicit def stringToWeekday(s: String): Weekday = Weekday.withName(s)
}

object Enumerations {
  import Weekday._
  println("Welcome to the Scala worksheet")

  def parseEnumeration[T <: Enumeration](s: String)(implicit ev: T): T#Value = {
    ev.withName(s)
  }

 val test = parseEnumeration[Weekday]("MONDAY")
}

那么我如何编写一个泛型函数,将枚举类型作为参数并返回该类型的值?我对 Object 和同名的内部类型有点困惑。

【问题讨论】:

标签: scala generics enumeration


【解决方案1】:

首先,您的隐式方法valueToWeekday 并没有真正做任何事情,因为Weekday 在这种情况下只是Value 的别名。

其次,您的隐式方法stringToWeekday 是一种有效的,尽管是从字符串到其枚举值的非泛型转换。

但是,将stringToWeekday 设为通用并不难。您只需将枚举传递给函数,就像在parseEnumeration 中所做的那样。由于您在 parseEnumeration 中隐含了证据,因此您需要做的就是在上下文中放置一个适当的隐含值。或者,您可以明确传递证据。

因此您可以删除那些隐式转换(以及类型别名,因为名称冲突有点误导)。

object Weekday extends Enumeration {
  val Monday = Value("MONDAY")
  val Other = Value("OTHER")
}
  1. 隐式方式:

    def parseEnumeration[T <: Enumeration](s: String)(implicit ev: T): T#Value = ev.withName(s)
    
    implicit val evidence = Weekday
    val weekday = parseEnumeration("MONDAY") // results in the value Weekday.Monday
    
  2. 显式方式:

    def parseEnumeration[T <: Enumeration](s: String, enumeration: T): T#Value = enumeration.withName(s)
    
    val weekday = stringToEnumerationValue("MONDAY", Weekday) // results in the value Weekday.Monday
    

第三种选择是使用ClassTag 作为证据,编译器通过泛型参数将其放入上下文中。但是,这需要反射才能实际调用方法withName,我不鼓励这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 1970-01-01
    相关资源
    最近更新 更多