一个枚举是用来定义一个类型,这个类型是命名值类型的集合。
翻译: http://dotty.epfl.ch/docs/reference/enums/enums.html#implementation
enum Color {
case Red, Green, Blue
}
这里定义了一个新的sealed
类 Color
,带有三个值: Color.Red
, Color.Green
, Color.Blue
.这些颜色值是Color
伴随对象的成员,以上Color
的定义和下面更明确的enum class
和伴随对象的定义是等价的:
enum class Color
object Color {
case Red
case Green
case Blue
}
参数化枚举
枚举类可以被参数化.
enum Color(val rgb: Int) {
case Red extends Color(0xFF0000)
case Green extends Color(0x00FF00)
case Blue extends Color(0x0000FF)
}
由这个例子所示,你可以通过extends
语句来参数化枚举.
枚举类型所定义的方法
一个枚举的值对应一个唯一的整数,这个整数可以通过enumTag
方法返回.
scala> val red = Color.Red
val red: Color = Red
scala> red.enumTag
val res0: Int = 0
一个枚举类的伴随对象也定义三个方法。 这个enumValue
和enumValueNamed
方法通过他的标签和名称获取值. 这个enumValues
方法获得所有枚举的值,存储在Iterable
集合中。
scala> Color.enumValue(1)
val res1: Color = Green
scala> Color.enumValueNamed("Blue")
val res2: Color = Blue
scala> Color.enumValues
val res3: collection.Iterable[Color] = MapLike(Red, Green, Blue)
枚举的自定义方法
你能在枚举类或伴随对象中添加自定义方法。你必须用更长的语法定义一个枚举类和他的伴随对象.下面的例子中,类Planet
定义了成员参数和成员相关的方法,在他的伴随对象中定义了枚举的所有值和入口方法main
enum class Planet(mass: Double, radius: Double) {
private final val G = 6.67300E-11
def surfaceGravity = G * mass / (radius * radius)
def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
}
object Planet {
case MERCURY extends Planet(3.303e+23, 2.4397e6)
case VENUS extends Planet(4.869e+24, 6.0518e6)
case EARTH extends Planet(5.976e+24, 6.37814e6)
case MARS extends Planet(6.421e+23, 3.3972e6)
case JUPITER extends Planet(1.9e+27, 7.1492e7)
case SATURN extends Planet(5.688e+26, 6.0268e7)
case URANUS extends Planet(8.686e+25, 2.5559e7)
case NEPTUNE extends Planet(1.024e+26, 2.4746e7)
def main(args: Array[String]) = {
val earthWeight = args(0).toDouble
val mass = earthWeight/EARTH.surfaceGravity
for (p <- enumValues)
println(s"Your weight on $p is ${p.surfaceWeight(mass)}")
}
}
枚举的具体实现
枚举类是个sealed
类,继承自scala.Enum
trait,这个trait定义了唯一个方法enumTag
:
package scala
/** A base trait of all enum classes */
trait Enum {
/** A number uniquely identifying a case of an enum */
def enumTag: Int
}
使用extends
语句枚举的值,同样可以展开为匿名类实例,比如:
val VENUS: Planet =
new Planet(4.869E24, 6051800.0) {
def enumTag: Int = 1
override def toString: String = "VENUS"
// internal code to register value
}
而没有使用extends
语句的所有枚举值共享单一实例,这个实例使用带有一个标签和名称的私有方法实例化,比如上面的Color.Red
展开为:
val Red: Color = $new(0, "Red")