使用密封的特征和案例对象

扩展 Enumeration 的另一种方法是使用 sealed case 对象:

sealed trait WeekDay

object WeekDay {
  case object Mon extends WeekDay
  case object Tue extends WeekDay
  case object Wed extends WeekDay
  case object Thu extends WeekDay
  case object Fri extends WeekDay
  case object Sun extends WeekDay
  case object Sat extends WeekDay
}

sealed 关键字保证特征 WeekDay 不能在另一个文件中扩展。这允许编译器做出某些假设,包括已经枚举了 WeekDay 的所有可能值。

一个缺点是此方法不允许你获取所有可能值的列表。要获得这样的列表,必须明确提供:

val allWeekDays = Seq(Mon, Tue, Wed, Thu, Fri, Sun, Sat)

案例类也可以扩展 sealed 特征。因此,可以混合对象和案例类来创建复杂的层次结构:

sealed trait CelestialBody
    
object CelestialBody {
  case object Earth extends CelestialBody
  case object Sun extends CelestialBody
  case object Moon extends CelestialBody
  case class Asteroid(name: String) extends CelestialBody
}

另一个缺点是无法访问 sealed 对象的枚举的变量名,或者通过它进行搜索。如果你需要与每个值关联的某种名称,则必须手动定义:

  sealed trait WeekDay { val name: String }

  object WeekDay {
      case object Mon extends WeekDay { val name = "Monday" }
      case object Tue extends WeekDay { val name = "Tuesday" }
      (...)   
  }

要不就:

  sealed case class WeekDay(name: String)
    
  object WeekDay {
      object Mon extends WeekDay("Monday")
      object Tue extends WeekDay("Tuesday")
      (...)   
  }