我在scala中有一个枚举映射到JPA中的字符串。为了更舒适的编码,我定义了它们之间的隐式转换。所以我现在可以定义值val person.role = "User"
, - person.role
是枚举类型"User"
一个字符串,所以有转换。但是当我尝试比较这两个时,我总是得到假,因为def equals (arg0: Any) : Boolean
需要Any
所以没有触发任何转换。我需要一些明确的转换,但我的计划是能够省略,你认为什么是最佳实践这里最好的解决方案?
答案 0 :(得分:16)
Value("User")
中的Enumeration
类型为Val
。我相信equals
的实现不会比较值的字符串名称。我认为这样做的一个重要方法是创建自己的Enumeration
和Val
,以便在名称匹配时返回true。
但是在我的代码中使用而不是JPA,我总是将字符串转换为MyEnumeration.Value
。这很容易,例如:
object E extends Enumeration { val User = Value("User") }
scala> val a = E.withName("User")
a: E.Value = User
请注意,使用withName
时,如果字符串与枚举中的任何名称都不匹配,则会出现异常。
然后始终使用比较中的枚举字段:
scala> a == E.User
res9: Boolean = true
如果JPA只返回一个字符串,则无法绕过它。然后我认为最好的选择是将值转换为字符串并将字符串与字符串匹配,或者将字符串升级为Val并比较Val。混合这些类型不能用于比较,除非您对equals
方法实现某种扩展,这很棘手。
答案 1 :(得分:15)
扩展Thomas的答案,如果你使用比较分支,使用模式匹配可能更合适:
object Role extends Enumeration {
val User = MyValue("User")
val Admin = MyValue("Admin")
def MyValue(name: String): Value with Matching =
new Val(nextId, name) with Matching
// enables matching against all Role.Values
def unapply(s: String): Option[Value] =
values.find(s == _.toString)
trait Matching {
// enables matching against a particular Role.Value
def unapply(s: String): Boolean =
(s == toString)
}
}
然后您可以按如下方式使用它:
def allowAccess(role: String): Boolean = role match {
case Role.Admin() => true
case Role.User() => false
case _ => throw ...
}
或
// str is a String
str match {
case Role(role) => // role is a Role.Value
case Realm(realm) => // realm is a Realm.Value
...
}