Enumerations
An enumeration is used to define a type consisting of a set of named values.
enum Color {
case Red, Green, Blue
}
This defines a new sealed
class, Color
, with three values, Color.Red
,
Color.Green
, Color.Blue
. The color values are members of Color
s
companion object.
Parameterized enums
Enums can be parameterized.
enum Color(val rgb: Int) {
case Red extends Color(0xFF0000)
case Green extends Color(0x00FF00)
case Blue extends Color(0x0000FF)
}
As the example shows, you can define the parameter value by using an explicit extends clause.
Methods defined for enums
The values of an enum correspond to unique integers. The integer
associated with an enum value is returned by its ordinal
method:
scala> val red = Color.Red
val red: Color = Red
scala> red.ordinal
val res0: Int = 0
The companion object of an enum also defines two utility methods.
The valueOf
method obtains an enum value
by its name. The values
method returns all enum values
defined in an enumeration in an Array
.
scala> Color.valueOf("Blue")
val res0: Color = Blue
scala> Color.values
val res1: Array[Color] = Array(Red, Green, Blue)
User-defined members of enums
It is possible to add your own definitions to an enum. Example:
enum Planet(mass: Double, radius: Double) {
private final val G = 6.67300E-11
def surfaceGravity = G * mass / (radius * radius)
def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
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)
}
It is also possible to define an explicit companion object for an enum:
object Planet {
def main(args: Array[String]) = {
val earthWeight = args(0).toDouble
val mass = earthWeight / Earth.surfaceGravity
for (p <- values)
println(s"Your weight on $p is ${p.surfaceWeight(mass)}")
}
}
Compatibility with Java Enums
If you want to use the Scala-defined enums as Java enums, you can do so by extending java.lang.Enum
class as follows:
enum Color extends java.lang.Enum[Color] { case Red, Green, Blue }
The type parameter comes from the Java enum definition and should be the same as the type of the enum.
There is no need to provide constructor arguments (as defined in the Java API docs) to java.lang.Enum
when extending it – the compiler will generate them automatically.
After defining Color
like that, you can use it like you would a Java enum:
scala> Color.Red.compareTo(Color.Green)
val res15: Int = -1
For a more in-depth example of using Scala 3 enums from Java, see this test. In the test, the enums are defined in the MainScala.scala
file and used from a Java source, Test.java
.
Implementation
Enums are represented as sealed
classes that extend the scala.Enum
trait.
This trait defines a single public method, ordinal
:
package scala
/** A base trait of all enum classes */
trait Enum {
/** A number uniquely identifying a case of an enum */
def ordinal: Int
}
Enum values with extends
clauses get expanded to anonymous class instances.
For instance, the Venus
value above would be defined like this:
val Venus: Planet =
new Planet(4.869E24, 6051800.0) {
def ordinal: Int = 1
override def toString: String = "Venus"
// internal code to register value
}
Enum values without extends
clauses all share a single implementation
that can be instantiated using a private method that takes a tag and a name as arguments.
For instance, the first
definition of value Color.Red
above would expand to:
val Red: Color = $new(0, "Red")
Reference
For more info, see Issue #1970 and PR #4003.