Scala不用关注枚举的特别语法,取而代之的是标准库中的类:scala.Enumeration
object Main extends App {
object WeekDay extends Enumeration {
type WeekDay = Value//这里仅仅是为了将Enumration.Value的类型暴露出来给外界使用而已
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value//在这里定义具体的枚举实例
}
import WeekDay._
def isWorkingDay(d: WeekDay) = ! (d == Sat || d == Sun)
WeekDay.values filter isWorkingDay foreach println//使用语法糖进行输出
}
上述是源码中给的一个枚举Example,可以发现:
构造函数以有变量
/** Defines a finite set of values specific to the enumeration. Typically
* these values enumerate all possible forms something can take and provide
* a lightweight alternative to case classes.
*
* Each call to a `Value` method adds a new unique value to the enumeration.
* To be accessible, these values are usually defined as `val` members of
* the evaluation.
*
* All values in an enumeration share a common, unique type defined as the
* `Value` type member of the enumeration (`Value` selected on the stable
* identifier path of the enumeration instance).
*
* @param initial The initial value from which to count the integers that
* identifies values at run-time.
* @author Matthias Zenger
*/
@SerialVersionUID(8476000850333817230L)
abstract class Enumeration (initial: Int) extends Serializable {
thisenum =>
def this() = this(0)
/** The mapping from the integer used to identify values to the actual
* values. */
private val vmap: mutable.Map[Int, Value] = new mutable.HashMap
/** The cache listing all values of this enumeration. */
@transient private var vset: ValueSet = null
@transient @volatile private var vsetDefined = false
/** The mapping from the integer used to identify values to their
* names. */
private val nmap: mutable.Map[Int, String] = new mutable.HashMap
/** The values of this enumeration as a set.
*/
def values: ValueSet = {
if (!vsetDefined) {
vset = (ValueSet.newBuilder ++= vmap.values).result()
vsetDefined = true
}
vset
}
/** The integer to use to identify the next created value. */
protected var nextId: Int = initial
/** The string to use to name the next created value. */
protected var nextName: Iterator[String] = _
private def nextNameOrNull =
if (nextName != null && nextName.hasNext) nextName.next else null
/** The highest integer amongst those used to identify values in this
* enumeration. */
private var topId = initial
/** The lowest integer amongst those used to identify values in this
* enumeration, but no higher than 0. */
private var bottomId = if(initial < 0) initial else 0
/** The one higher than the highest integer amongst those used to identify
* values in this enumeration. */
final def maxId = topId
上面是洋洋洒洒贴了Enumeration类在Scala中的部分源码,从中大致可以看到这么几个关键点:
/** The type of the enumerated values. */
@SerialVersionUID(7091335633555234129L)
abstract class Value extends Ordered[Value] with Serializable {
/** the id and bit location of this enumeration value */
def id: Int
/** a marker so we can tell whose values belong to whom come reflective-naming time */
private[Enumeration] val outerEnum = thisenum
override def compare(that: Value): Int =
if (this.id < that.id) -1
else if (this.id == that.id) 0
else 1
override def equals(other: Any) = other match {
case that: Enumeration#Value => (outerEnum eq that.outerEnum) && (id == that.id)
case _ => false
}
override def hashCode: Int = id.##
/** Create a ValueSet which contains this value and another one */
def + (v: Value) = ValueSet(this, v)
}
在源码的Example中可以看到所有的枚举都是被赋值为Value类型,从上面的源码中可以看到Value类是一个抽象类,看它的内容只是提供了枚举值比较以及id的获取,在Enumeration源码中提供了一个叫Val的类对Value实现,重要是重写了整数命名和id的识别。
/** A class implementing the [[scala.Enumeration.Value]] type. This class
* can be overridden to change the enumeration's naming and integer
* identification behaviour.
*/
@SerialVersionUID(0 - 3501153230598116017L)
protected class Val(i: Int, name: String) extends Value with Serializable {
def this(i: Int) = this(i, nextNameOrNull)
def this(name: String) = this(nextId, name)
def this() = this(nextId)
//to do many things.
}
请注意,请注意,Example中的第4行、第5行的Value,前者是类,后者是方法(括号省略了而已)
/** Creates a fresh value, part of this enumeration. */
protected final def Value: Value = Value(nextId)
/** Creates a fresh value, part of this enumeration, identified by the
* integer `i`.
*
* @param i An integer that identifies this value at run-time. It must be
* unique amongst all values of the enumeration.
* @return Fresh value identified by `i`.
*/
protected final def Value(i: Int): Value = Value(i, nextNameOrNull)
/** Creates a fresh value, part of this enumeration, called `name`.
*
* @param name A human-readable name for that value.
* @return Fresh value called `name`.
*/
protected final def Value(name: String): Value = Value(nextId, name)
/** Creates a fresh value, part of this enumeration, called `name`
* and identified by the integer `i`.
*
* @param i An integer that identifies this value at run-time. It must be
* unique amongst all values of the enumeration.
* @param name A human-readable name for that value.
* @return Fresh value with the provided identifier `i` and name `name`.
*/
protected final def Value(i: Int, name: String): Value = new Val(i, name)
上面提供了各种Value的重载方法均是返回了Val类,所以说嘛,你有需要完全可以自己再实现一个Value类。
println(WeekDay.Wed)//直接取枚举值
println(WeekDay.Wed.id)//取枚举值所在序号
println(WeekDay.maxId)//枚举值的个数
println(WeekDay.withName("Wed"))//通过字符串获取枚举(这里是不需要反射的)
获取枚举的具体信息还是非常方便的
Wed
2
7
Wed
获取全部的枚举值进行输出
WeekDay.values.foreach(println(_))
Mon
Tue
Wed
Thu
Fri
Sat
Sun
枚举也可以用在匹配
matchTest(WeekDay.Wed)
matchTest(WeekDay.Sat)
def matchTest=(week:WeekDay.Value) =>week match{//注意,这里枚举的类型都是Value
case w if w.compare(WeekDay.Fri)<=0 =>println("sorry,please working")
case WeekDay.Sat=>println(("go shopping"))
case WeekDay.Sun=>println(("sleeping"))
}
可以看到输出
sorry,please working
go shopping
这里的枚举值的比较其实就是对比他们的Id是否相等。
http://www.cnblogs.com/gnivor/p/4191017.html
Enumeration.scala
https://toutiao.io/posts/g9ktuv/preview