Scala 枚举介绍及深入应用
- 作者: 五速梦信息网
- 时间: 2026年04月04日 13:28
本文详细地总结了Scala枚举的几种实现方式,对我们更好地进行函数式编程有很好地指导和帮助。
Scala 枚举示例和特性
Scala
object Weekday extends Enumeration {
val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = Value
}
StringIntScala
- 序列化和反序列化方法(Serialize and Deserialize methods),这些方法也会抛出异常:(:
scala> Weekday.Monday.toString
res0: String = Monday
scala> Weekday.withName("Monday")
res1: Weekday.Value = Monday
scala> Weekday.withName("Mondai")
java.util.NoSuchElementException: No value found for 'Mondai'
at scala.Enumeration.withName(Enumeration.scala:124)
... 32 elided
- 提供可读性(human-readable value)的值:
object Weekday extends Enumeration {
val Monday = Value("Mo.")
val Tuesday = Value("Tu.")
val Wednesday = Value("We.")
val Thursday = Value("Th.")
val Friday = Value("Fr.")
val Saturday = Value("Sa.")
val Sunday = Value("Su.")
}
scala> Weekday.Monday.toString
res0: String = Mo.
- 列出所有可能的值:
scala> Weekday.values
res0: Weekday.ValueSet = Weekday.ValueSet(Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
- 排序(Ordering)。默认情况下,枚举值是按照声明的顺序排序的,排序顺序可以通过覆盖(overridden)原来枚举值的方式改变:
object Weekday extends Enumeration {
val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = Value
}
// 按照枚举值声明的顺序排序
scala> Weekday.values.toList.sorted
res0: List[Weekday.Value] = List(Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
object Weekday extends Enumeration {
val Monday = Value(1)
val Tuesday = Value(2)
val Wednesday = Value(3)
val Thursday = Value(4)
val Friday = Value(5)
val Saturday = Value(6)
val Sunday = Value(0)
}
// 按照枚举对应的数字值排序
scala> Weekday.values.toList.sorted
res1: List[Weekday.Value] = List(Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday)
scala.Enumeration的问题
然而,这种方法有一些问题。主要有两个缺点:
- 擦除(erasure)后枚举具有相同的类型:
object Weekday extends Enumeration {
val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = Value
}
object OtherEnum extends Enumeration {
val A, B, C = Value
}
def test(enum: Weekday.Value) = {
println(s"enum: $enum")
}
def test(enum: OtherEnum.Value) = {
println(s"enum: $enum")
}
<console>:25: error: double definition:
def test(enum: Weekday.Value): Unit at line 21 and
def test(enum: OtherEnum.Value): Unit at line 25
have same type after erasure: (enum: Enumeration#Value)Unit
def test(enum: OtherEnum.Value) = {
^
- 在编译期间没有详尽的匹配检查(matching check)。下面的示例将在没有任何警告的情况下编译,但是在对周一和周日以外的工作日匹配时会抛出scala.MatchError异常:
def nonExhaustive(weekday: Weekday.Value) {
weekday match {
case Monday => println("I hate Mondays")
case Sunday => println("The weekend is already over? :( ")
}
}
在Scala中,我们严重依赖于编译器强大的类型系统,使用这种方法,编译器不能找到非穷尽模式匹配子句,也不能对不同的枚举使用重载方法。
为了避免这种问题,我们可以其他办法实现枚举:
- 使用密封盒对象(sealed case objects)
- 分项(itemized)
- enumeratum
Sealed case objects
sealed case objectsScalaScala
sealed trait Weekday
case object Monday extends Weekday
case object Tuesday extends Weekday
case object Wednesday extends Weekday
case object Thursday extends Weekday
case object Friday extends Weekday
case object Saturday extends Weekday
case object Sunday extends Weekday
def test(weekday: Weekday) = {
weekday match {
case Monday => println("I hate Mondays")
case Sunday => println("The weekend is already over? :( ")
}
}
<console>:15: warning: match may not be exhaustive.
It would fail on the following inputs: Friday, Saturday, Thursday, Tuesday, Wednesday
weekday match {
^
test: (weekday: Weekday)Unit
sealed abstract classsealed trait
sealed abstract class Weekday( val name: String,
val abbreviation: String,
val isWorkDay: Boolean)
case object Monday extends Weekday("Monday", "Mo.", true)
case object Tuesday extends Weekday("Tuesday", "Tu.", true)
case object Wednesday extends Weekday("Wednesday", "We.", true)
case object Thursday extends Weekday("Thursday", "Th.", true)
case object Friday extends Weekday("Friday", "Fr.", true)
case object Saturday extends Weekday("Saturday", "Sa.", false)
case object Sunday extends Weekday("Sunday", "Su.", false)
sealed case objects的问题
但是这种方式也有它自己的问题:
- 没有检索所有枚举值的简单方法
- 没有默认的序列化/反序列化方法
- 枚举值之间没有默认的排序——这可以通过包含一些关于值的信息来手动实现,示例如下:
sealed abstract class Weekday( val name: String,
val abbreviation: String,
val isWeekDay: Boolean,
val order: Int) extends Ordered[Weekday] {
def compare(that: Weekday) = this.order - that.order
}
case object Monday extends Weekday("Monday", "Mo.", true, 2)
case object Tuesday extends Weekday("Tuesday", "Tu.", true, 3)
case object Wednesday extends Weekday("Wednesday", "We.", true, 4)
case object Thursday extends Weekday("Thursday", "Th.", true, 5)
case object Friday extends Weekday("Friday", "Fr.", true, 6)
case object Saturday extends Weekday("Saturday", "Sa.", false, 7)
case object Sunday extends Weekday("Sunday", "Su.", false, 1)
scala> Monday < Tuesday
res0: Boolean = true
分项(itemized)
Scala
itemized
import io.rbricks.itemized.annotation.enum
@enum trait Weekday {
object Monday
object Tuesday
object Wednesday
object Thursday
object Friday
object Saturday
object Sunday
}
itemized
- 列出所有枚举值
- 默认的序列化/反序列化方法
scala> import io.rbricks.itemized.ItemizedCodec
scala> ItemizedCodec[Weekday].fromRep("Monday")
res0: Option[Weekday] = Some(Monday)
scala> val weekday: Weekday = Planet.Monday
scala> import io.rbricks.itemized.ItemizedCodec.ops._
scala> weekday.toRep
res1: String = Earth
itemized的问题
itemized
enumeratum
Scala
import enumeratum._
sealed trait Weekday extends EnumEntry
object Weekday extends Enum[Weekday] {
val values = findValues // mandatory due to Enum extension
case object Monday extends Weekday
case object Tuesday extends Weekday
case object Wednesday extends Weekday
case object Thursday extends Weekday
case object Friday extends Weekday
case object Saturday extends Weekday
case object Sunday extends Weekday
}
def test(weekday: Weekday) = {
weekday match {
case Weekday.Monday => println("I hate Mondays")
case Weekday.Sunday => println("The weekend is already over? :( ")
}
}
<console>:18: warning: match may not be exhaustive.
It would fail on the following inputs: Friday, Saturday, Thursday, Tuesday, Wednesday
weekday match {
^
test: (weekday: Weekday)Unit
enumeratum
Enum
scala> Weekday.withName("Monday")
res0: Weekday = Monday
scala> Weekday.withName("Momday")
java.util.NoSuchElementException: Momday is not a member of Enum (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
at enumeratum.Enum$$anonfun$withName$1.apply(Enum.scala:82)
at enumeratum.Enum$$anonfun$withName$1.apply(Enum.scala:82)
at scala.Option.getOrElse(Option.scala:121)
at enumeratum.Enum$class.withName(Enum.scala:81)
at Weekday$.withName(<console>:13)
... 43 elided
scala> Weekday.withNameOption("Monday")
res2: Option[Weekday] = Some(Monday)
scala> Weekday.withNameOption("Momday")
res3: Option[Weekday] = None
- 向枚举添加额外的值。它非常类似于我们给简单的密封盒对象添加额外的值
sealed abstract class Weekday( val name: String,
val abbreviation: String,
val isWorkDay: Boolean) extends EnumEntry
case object Weekday extends Enum[Weekday] {
val values = findValues
case object Monday extends Weekday("Monday", "Mo.", true)
case object Tuesday extends Weekday("Tuesday", "Tu.", true)
case object Wednesday extends Weekday("Wednesday", "We.", true)
case object Thursday extends Weekday("Thursday", "Th.", true)
case object Friday extends Weekday("Friday", "Fr.", true)
case object Saturday extends Weekday("Saturday", "Sa.", false)
case object Sunday extends Weekday("Sunday", "Su.", false)
}
- 排序可以通过与封闭层次(sealed hierarchies)结构相同的方式实现。只需与有序[]特质(trait)混合,并实现比较方法。
sealed abstract class Weekday(val order: Int) extends EnumEntry with Ordered[Weekday] {
def compare(that: Weekday) = this.order - that.order
}
object Weekday extends Enum[Weekday] {
val values = findValues
case object Monday extends Weekday(2)
case object Tuesday extends Weekday(3)
case object Wednesday extends Weekday(4)
case object Thursday extends Weekday(5)
case object Friday extends Weekday(6)
case object Saturday extends Weekday(7)
case object Sunday extends Weekday(1)
}
总结
Scalascala.EnumerationScala
sealed hierarchiesenumeratum
枚举特性总结
- 详尽的模式匹配
- 没有类型擦除
- 安全的序列化/反序列化的默认方法
- 列出所有可能的值
- 在枚举值上添加额外的字段
- 排序
Scala
相关文章
-
scala.的Enumeration枚举示例(转)
scala.的Enumeration枚举示例(转)
- 互联网
- 2026年04月04日
-
scala本地删除文件夹
scala本地删除文件夹
- 互联网
- 2026年04月04日
-
scala中获取Map中key和value的方法
scala中获取Map中key和value的方法
- 互联网
- 2026年04月04日
-
scala 两个map合并,key相同时value相加相减都可
scala 两个map合并,key相同时value相加相减都可
- 互联网
- 2026年04月04日
-
scala 反射 object
scala 反射 object
- 互联网
- 2026年04月04日
-
scala map 根据 key 获取value
scala map 根据 key 获取value
- 互联网
- 2026年04月04日






