我有一个简单的枚举:
object ConditionOperator extends Enumeration {
val Equal = Value("equal")
val NotEqual = Value("notEqual")
val GreaterOrEqual = Value("greaterOrEqual")
val Greater = Value("greater")
val LessOrEqual = Value("lessOrEqual")
val Less = Value("less")
我想为每个枚举添加一个方法,以便我可以像这样使用它:
def buildSqlCondition(field: String, operator: ConditionOperator.Value, value: String ) = {
val sqlOperator = operator.toSql
[...]
因此,ConditionOperator.Equal.toSql将返回“=”,而ConditionOperator.NotEqual.toSql将返回“<>”等...
但我不知道如何定义toSql方法,以便每个枚举可以“看到”它自己的值并决定如何将自己转换为sql运算符...
答案 0 :(得分:3)
您可以从定义覆盖Enumeration.Val
的内部类开始。为简化起见,我们称之为Value
(我们重载Value
中定义的Enumeration
的原始含义。
我们有了新的Value
类型,它继承了Enumeration.Val
,它本身继承了Enumeration.Value
。
鉴于toSql
没有副作用并为每个枚举返回不同的字符串,您可能只需将其设为val
。
最后,为了使其完全可用,您需要使用ConditionOperator.apply和ConditionOperator.withName来返回新定义的Value
类,而不是Value
中定义的Enumeration
类。 }}。
否则,当使用apply或withName按索引/名称查找ConditionOperator
的实例时,您将无法调用toSql,因为枚举类型不是特定的enoough。
理想情况下,我们只需覆盖apply
和withName
并向ConditionOperator.Value
添加强制转换,但这些方法是最终的。
但是我们可以在这里使用一个小技巧:定义具有相同签名的新方法apply
和withName
,但是另外一个永远可用的隐式参数(Predef.DummyImplicit完全适合这个rolle)。
附加参数确保签名不同,以便我们能够定义这些新方法,同时与原始apply / withName方法几乎无法区分。
在scala中重载分辨率的规则确保我们的新方法是编译器所青睐的方法(因此我们实际上已经隐藏了原始方法)。
object ConditionOperator extends Enumeration {
// Here we overload the meaning of "Value" to suit our needs
class Value(name: String, val toSql: String) extends super.Val(name) {
def someFlag: Boolean = true // An example of another method, that you can override below
}
val Equal = new Value("equal", "=")
val NotEqual = new Value("notEqual", "<>")
val GreaterOrEqual = new Value("greaterOrEqual", ">=")
val Greater = new Value("greater", ">")
val LessOrEqual = new Value("lessOrEqual", "<=") { override def someFlag = false }
val Less = new Value("less", "<")
final def apply(x: Int)( implicit dummy: DummyImplicit ): Value = super.apply(x).asInstanceOf[Value]
final def withName(s: String)( implicit dummy: DummyImplicit ): Value = super.withName(s).asInstanceOf[Value]
}
您可以检查您现在可以执行ConditionOperator(2).toSql
或ConditionOperator.withName(“greaterOrEqual”)之类的操作,它们都按预期返回“&gt; =”。
最后,上述体操可以抽象出来:
abstract class CustomEnumeration extends Enumeration {
type BaseValue = super.Val
type CustomValue <: super.Value
type Value = CustomValue
final def apply(x: Int)( implicit dummy: DummyImplicit ): CustomValue = super.apply(x).asInstanceOf[CustomValue]
final def withName(s: String)( implicit dummy: DummyImplicit ): CustomValue = super.withName(s).asInstanceOf[CustomValue]
}
object ConditionOperator extends CustomEnumeration {
class CustomValue(name: String, val toSql: String) extends BaseValue(name) {
def someFlag: Boolean = true
}
val Equal = new Value("equal", "=")
val NotEqual = new Value("notEqual", "<>")
val GreaterOrEqual = new Value("greaterOrEqual", ">=")
val Greater = new Value("greater", ">")
val LessOrEqual = new Value("lessOrEqual", "<=") { override def someFlag = false }
val Less = new Value("less", "<")
}