将枚举参数化为Enumeration in Enumeration

时间:2014-07-08 13:16:09

标签: scala enumeration

我正在尝试向apply添加函数Enumeration。我想将枚举值映射到函数,然后像这样使用它:

Action(DO_THIS, "Arg string")

应该打印它的值。我有多个枚举类,我试图通过特质mixin实现这个功能。到目前为止,我没有让编译器开心。我有这个不编译的代码:

trait EnumFunc [EnumType <: Enumeration] {
  protected def funcMappings: Map[EnumType#Value, Function1[String, Unit]]

  def apply(enum: EnumType#Value, arg: String): Unit =
    funcMappings.getOrElse(enum, (arg: String) => ())(arg)
}


trait Action extends Enumeration with EnumFunc[Action] {
  type Action = Value

  val DO_THIS, DO_THAT = Value

  override val funcMappings: Map[Action, Function1[String, Unit]] =
    Map(DO_THIS -> ((arg: String) => println(arg)))
}

object Action extends Action

编译器产生此错误:

error: overriding method funcMappings in trait EnumFunc of type => Map[Action#Value,String => Unit];
 value funcMappings has incompatible type
         override val funcMappings: Map[Action, Function1[String, Unit]] =

我无法确切地知道问题是什么。有人可以解释一下是否有可能实现这一目标以及为什么这不能编译?

1 个答案:

答案 0 :(得分:1)

ValueAction内的

EnumType#Value并不完全相同。 Value内的Action是路径相关类型,它只能引用Values作为其父级this的实例,即Valuethis.Value的同义词。 EnumType#Value是一种类型投影,它可以引用EnumType实例中的任何值,而不关心它的父级是什么。因此,funcMappingsapplyAction的声明实际上被赋予更严格的参数类型,这不是类型安全的。

但是,实际上并不需要EnumType上的类型参数,如果您扩展Enumeration,则可以直接使用Value

trait EnumFunc extends Enumeration {
  protected def funcMappings: Map[Value, Function1[String, Unit]]

  def apply(enum: Value, arg: String): Unit =
    funcMappings.getOrElse(enum, (arg: String) => ())(arg)
}

然后它会工作。然而,这只是斯卡拉Enumeration如何憎恶的众多例子之一。一旦您知道要为各个元素添加方法,最好使用案例类/对象的层次结构:

abstract class Doers {
  def apply(s: String): Unit
}
case object DoThis extends Doers {
  def apply(s: String): Unit = println(s)
}
case object DoThat extends Doers {
  def apply(s: String): Unit = ???
}