scala 比较字符串和枚举
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3407032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Comparing String and Enumeration
提问by coubeatczech
I have an enumeration in scala mapped to strings in JPA. For more comfortable coding, I defined implicit conversions between them. So I now can define value val person.role = "User", - person.roleis the enumeration type "User"a String so there's the conversion. But when I try to compare these two, I always get false, because the def equals (arg0: Any) : Booleantakes Anyso there's not any conversion triggered. I need some explicit conversion, but my plan was to be able to omit that, what do you think is the best practice | neatest solution here?
我在 Scala 中有一个枚举映射到 JPA 中的字符串。为了更舒适的编码,我定义了它们之间的隐式转换。所以我现在可以定义 value val person.role = "User", -person.role枚举类型"User"是一个 String 所以有转换。但是,当我尝试这两个比较,我总是假的,因为def equals (arg0: Any) : Boolean需要Any所以没有触发任何转换。我需要一些显式转换,但我的计划是能够省略它,您认为最佳实践是什么?这里最好的解决方案?
回答by Thomas
The Value("User")in your Enumerationis of type Val. And I believe it's implementation of equalsdoes not compare the string name of the value. I think one heavy handed way of doing this is creating your own Enumerationand Valso that it returns true if the name match.
在Value("User")你Enumeration的类型的Val。而且我相信它的实现equals不会比较值的字符串名称。我认为这样做的一种严厉方法是创建自己的方法Enumeration,Val以便在名称匹配时返回 true。
But in my code uses, not with JPA, I always convert the string into the MyEnumeration.Value. This is easy with things like:
但是在我的代码使用中,而不是使用 JPA,我总是将字符串转换为MyEnumeration.Value. 这很容易,例如:
object E extends Enumeration { val User = Value("User") }
scala> val a = E.withName("User")
a: E.Value = User
Note that when using withName, if the string does not match any name in the enumeration you get an exception.
请注意,在使用时withName,如果字符串与枚举中的任何名称都不匹配,则会出现异常。
Then always use the enumeration fields in your comparisons:
然后始终在比较中使用枚举字段:
scala> a == E.User
res9: Boolean = true
If JPA only returns a string, and there is no way around it. Then I think the best option is to either convert the value to string and match string to string, or upgrade the string to a Val and compare Val. Mixing these types will not work for comparison, unless you you implement some kind of extension to the equalsmethod, and that is tricky.
如果 JPA 只返回一个字符串,则没有办法绕过它。然后我认为最好的选择是将值转换为字符串并将字符串匹配到字符串,或者将字符串升级为 Val 并比较 Val。混合这些类型将无法进行比较,除非您对该equals方法实施某种扩展,这很棘手。
回答by Aaron Novstrup
Expanding on Thomas's answer, if you're using the comparison to branch, using pattern matching may be more appropriate:
扩展托马斯的答案,如果您使用比较分支,使用模式匹配可能更合适:
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)
}
}
You can then use this as follows:
然后,您可以按如下方式使用它:
def allowAccess(role: String): Boolean = role match {
case Role.Admin() => true
case Role.User() => false
case _ => throw ...
}
or
或者
// str is a String
str match {
case Role(role) => // role is a Role.Value
case Realm(realm) => // realm is a Realm.Value
...
}

