11. Enums
Overview
Enums are a special type of class that define a discrete range of possible values:
- Enums are normal classes with all associated characteristics
- Enums are implied const
- Enums are implied final
- Enums have a fixed range of instances
- Enums can contain declare zero or more uniquely named slots
- Enums always always inherit from
Enum
- Enums may inherit zero or more mixins
- Enums must have private constructors
Enums are declared using the enum
positional keyword and must declare their range of values before any other slot declarations:
enum class Color { red, blue, green }
Range
The range of an enum is its discrete set of instances. Each instance of the range has the following characteristics:
- is identified by a unique zero based ordinal
- is identified by a unique name
- is accessed via a static const field by its name
- is an instance of the declaring enum class
- is immutable (enums are implied const)
The compiler automatically generates two helper slots:
vals
is a list of all the values in the range indexed by ordinalfromStr
is used to resolve by name
Consider this example to illustrate what happens under the covers:
// what you write enum class Color { red, blue, green } // what the compiler generates class Color : Enum { static const Color red = make(0, "red") static const Color blue = make(1, "blue") static const Color green = make(2, "green") static const Color[] vals = [red, blue, green].toImmutable static new fromStr(Str s) { ... } private new make(Int ord, Str name) : super(ord, name) {} }
Enum Constructors
Enums can declare their own constructor to initialize additional fields. Remember that an enum is const, which means that all its fields must also be const. This in turn means that all fields must be initialized in the constructor. Enum constructors must be private. The following syntax is used to declare and call an enum constructor:
enum class Suits { clubs("black"), diamonds("red"), hearts("red"), spades("black") private new make(Str color) { this.color = color; } const Str color; }
Note that the declaring class doesn't actually manage its own ordinals and names, this is always done by the compiler.
Enum Modifiers
Enums can be annotated with the public
or internal
modifiers just like classes. It is a compile time error to use the abstract
, final
, or const
modifiers with a enum - final
and const
are implied.
Reflection
Enums are keyed by both an zero based integer ordinal and a string name. The following summarizes slots often used to work with enums (using Month
as an example):
Enum.ordinal
: theInt
ordinal keyEnum.name
: theStr
name keyMonth.vals
: lookup instance by ordinalMonth.fromStr
: lookup instance by name
Example code:
apr := Month.apr // direct access jun := Month.vals[5] // lookup by ordinal aug := Month.fromStr("aug") // lookup by name Month.fromStr("bad") // throws ParseErr Month.fromStr("bad", false) // returns null