比较字符串和枚举

cou*_*ech 10 scala

我在scala中有一个枚举映射到JPA中的字符串.为了更舒适的编码,我定义了它们之间的隐式转换.所以我现在可以定义值val person.role = "User", - person.role枚举类型"User"是一个String,所以有转换.但是,当我尝试这两个比较,我总是假的,因为def equals (arg0: Any) : Boolean需要Any所以没有触发任何转换.我需要一些明确的转换,但我的计划是能够省略,你认为什么是最佳实践 这里最好的解决方案?

Tho*_*mas 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
Run Code Online (Sandbox Code Playgroud)

请注意,在使用时withName,如果字符串与枚举中的任何名称都不匹配,则会出现异常.

然后始终在比较中使用枚举字段:

scala> a == E.User
res9: Boolean = true
Run Code Online (Sandbox Code Playgroud)

如果JPA只返回一个字符串,并且无法绕过它.然后我认为最好的选择是将值转换为字符串并将字符串与字符串匹配,或者将字符串升级为Val并比较Val.混合这些类型不能用于比较,除非您对该equals方法实现某种扩展,这很棘手.


Aar*_*rup 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)
   }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以按如下方式使用它:

def allowAccess(role: String): Boolean = role match {
   case Role.Admin() => true
   case Role.User() => false
   case _ => throw ...
}
Run Code Online (Sandbox Code Playgroud)

要么

// str is a String
str match { 
   case Role(role) => // role is a Role.Value
   case Realm(realm) => // realm is a Realm.Value
   ...
}
Run Code Online (Sandbox Code Playgroud)