我正在尝试向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]] =
我无法确切地知道问题是什么。有人可以解释一下是否有可能实现这一目标以及为什么这不能编译?
答案 0 :(得分:1)
Value
和Action
内的 EnumType#Value
并不完全相同。 Value
内的Action
是路径相关类型,它只能引用Values
作为其父级this
的实例,即Value
是this.Value
的同义词。 EnumType#Value
是一种类型投影,它可以引用EnumType
实例中的任何值,而不关心它的父级是什么。因此,funcMappings
中apply
和Action
的声明实际上被赋予更严格的参数类型,这不是类型安全的。
但是,实际上并不需要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 = ???
}