import enumeratum._
sealed trait Greeting extends EnumEntry
object Greeting extends Enum[Greeting] {
/*
`findValues` is a protected method that invokes a macro to find all `Greeting` object declarations inside an `Enum`
You use it to implement the `val values` member
*/
val values = findValues
case object Hello extends Greeting
case object GoodBye extends Greeting
case object Hi extends Greeting
case object Bye extends Greeting
}
// Object Greeting has a `withName(name: String)` method
Greeting.withName("Hello")
// => res0: Greeting = Hello
Greeting.withName("Haro")
// => java.lang.IllegalArgumentException: Haro is not a member of Enum (Hello, GoodBye, Hi, Bye)
// A safer alternative would be to use `withNameOption(name: String)` method which returns an Option[Greeting]
Greeting.withNameOption("Hello")
// => res1: Option[Greeting] = Some(Hello)
Greeting.withNameOption("Haro")
// => res2: Option[Greeting] = None
// It is also possible to use strings case insensitively
Greeting.withNameInsensitive("HeLLo")
// => res3: Greeting = Hello
Greeting.withNameInsensitiveOption("HeLLo")
// => res4: Option[Greeting] = Some(Hello)
// Uppercase-only strings may also be used
Greeting.withNameUppercaseOnly("HELLO")
// => res5: Greeting = Hello
Greeting.withNameUppercaseOnlyOption("HeLLo")
// => res6: Option[Greeting] = None
// Similarly, lowercase-only strings may also be used
Greeting.withNameLowercaseOnly("hello")
// => res7: Greeting = Hello
Greeting.withNameLowercaseOnlyOption("hello")
// => res8: Option[Greeting] = Some(Hello)
9 回答
在对Scala中的"enumerations"周围的所有选项进行了广泛的研究之后,我在另一个StackOverflow thread上发布了关于该域的更全面的概述 . 它包含了"sealed trait + case object"模式的解决方案,我解决了JVM类/对象初始化排序问题 .
Dotty(Scala 3)将支持原生枚举 . 检查here和here .
http://www.scala-lang.org/docu/files/api/scala/Enumeration.html
使用示例
我必须说上面skaffman从Scala文档中复制的示例在实践中的实用性有限(你不妨使用
case object
) .为了获得最接近Java
Enum
的东西(即使用合理的toString
和valueOf
方法 - 也许你将枚举值保存到数据库中),你需要稍微修改一下 . 如果您使用过skaffman的代码:而使用以下声明:
你会得到更明智的结果:
有很多方法可以做 .
1)使用符号 . 但是,除了不接受符号所在的非符号之外,它不会给你任何类型安全 . 我只是在这里提到完整性 . 这是一个用法示例:
2)使用类
Enumeration
:或者,如果您需要序列化或显示它:
这可以这样使用:
不幸的是,它并没有警告过我 . 所以它给了我一些类型的安全性,但没有得到多少 .
3)案例对象:
现在,如果我在
match
上遗漏了一个案例,编译器会警告我:它's used pretty much the same way, and doesn'甚至需要一个
import
:那么,您可能想知道为什么要使用枚举而不是案例对象 . 事实上,案例对象确实具有很多次优势,例如这里 . 但是,Enumeration类有许多Collection方法,例如元素(Scala 2.8上的迭代器),它返回Iterator,map,flatMap,filter等 .
这个答案基本上是我博客中this article的一个选定部分 .
一种稍微冗长的声明命名枚举的方式:
当然,这里的问题是你需要保持名称和val的顺序同步,如果在同一行上声明name和val,这将更容易 .
您可以使用密封的抽象类而不是枚举,例如:
刚刚发现enumeratum . 它's pretty amazing and equally amazing it'不是更为人所知!
在Scala中它非常舒服https://github.com/lloydmeta/enumeratum
项目非常好,包含示例和文档
只是他们的文档中的这个例子应该让你感兴趣