了解scala枚举


122

我不得不说我不理解Scala枚举类。我可以从文档中复制粘贴该示例,但是我不知道发生了什么。

object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
  • 什么意思type WeekDay = Value,为什么我要写那个?
  • 为什么val Mon = Value呢?那有什么意思?
  • 为什么必须导入WeekDay 对象?和,
  • 当我写的时候val day = WeekDay.Mon,为什么是打字WeekDay.Value,而不是打字WeekDay

2
我已经撰写了有关Scala枚举和替代方法的简短概述,您可能会发现它很有用:pedrorijo.com/blog/scala-enums/
pedrorijo91 2016年

Answers:


150

Enumeration特性有一个类型成员Value代表枚举(它实际上是一个内部类,但差异并不重要,在这里)的单个元素。

因此object WeekDay继承该类型成员。该行type WeekDay = Value只是一个类型别名。这很有用,因为在使用将其导入其他地方之后import WeekDay._,您可以使用该类型,例如:

def isWorkingDay(d: WeekDay) = ! (d == Sat || d == Sun)

相反,最低版本将是:

object WeekDay extends Enumeration {
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}

你不必须输入的内容object WeekDay,但你需要使用类型WeekDay.Value和资格个人会员。因此,示例将成为

def isWorkingDay(d: WeekDay.Value) = ! (d == WeekDay.Sat || d == WeekDay.Sun)

第二个问题是关于的含义val Mon, ... = Value。如果您不考虑的实现,这确实会造成混乱Enumeration。这不是类型的分配!这是不是调用一个受保护的同名方法Value,它返回类型的具体实例Value

恰巧,你可以写val a, b, c = foo在Scala中,并为每个值ab以及c该方法foo会被一次又一次地叫。Enumeration使用此技巧来递增内部计数器,以便每个值都是独立的。

如果打开的Scala API文档Enumeration并单击Visibility: All,则会看到该方法。


2
谢谢,这非常令人困惑,但我认为是正确的。我将改用密封的案例类,这似乎容易100%。
卡雷尔·比列克(KarelBílek)2012年

2
我个人也喜欢密封箱类。较详细,但内部计数器可变的hokus-pokus较少,依此类推。在Scala 2.10中,有一些想法如何使用宏更好地编写枚举(与Java不同,枚举不是语言构造,而只是库解决方案)。
0__

@ 0__请问为什么以及如何使用密封类替换Scala中的枚举?Scala的枚举有什么问题吗?
x1a0 2013年

如果Enum值本身有成员怎么办?例如,您如何定义一周中每一天的开放时间,例如:Mon(8,20),...,Sun(0,0)?
simou 2014年

1
@simou,那么您确实应该使用密封的特征和实际的子类。但是,我几乎不会将这种情况称为“枚举”。您可能会写得更好Open(Mon, 8, 20),并且日子将保持不变。
2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.