An enumeration type is a special class used to represent a fixed set of constant values.
All enums automatically inherit the Enum class. Enums are sealed types: they cannot be inherited, implemented, mixed in, nor instantiated explicitly by hand.
Abstract classes and mixins may explicitly implement or extend Enum, but you cannot create actual instances of such classes or mixins unless they are implemented or mixed into an enum declaration.
Define simple enums with the enum keyword by listing all enum constants:
enum Color { red, green, blue }
Trailing commas are permitted when declaring enums, which eases copy-paste operations and reduces coding mistakes.
Enhanced enums
Dart supports enhanced enums. You can define member fields, methods and constant constructors just like regular classes, yet instances are limited to predefined fixed constants.
Declaring enhanced enums comes with several mandatory constraints:
- All instance variables must be declared
final(including variables introduced from mixins) - Every generative constructor must be marked
const - Factory constructors can only return constant instances defined inside the enum
- No explicit inheritance from other classes (automatic inheritance from
Enum) - You cannot override
index,hashCode, or the equality operator== - No member named
valuesmay be defined inside the enum; this conflicts with the auto-generated staticvaluesaccessor - All enum instances must appear at the very start of the enum definition, and at least one instance is required
- Within instance methods of enhanced enums,
thisrefers to the current enum constant
Example
enum Vehicle implements Comparable<Vehicle> {
car(tires: 4, passengers: 5, carbonPerKilometer: 400),
bus(tires: 6, passengers: 50, carbonPerKilometer: 800),
bicycle(tires: 2, passengers: 1, carbonPerKilometer: 0);
const Vehicle({
required this.tires,
required this.passengers,
required this.carbonPerKilometer,
});
final int tires;
final int passengers;
final int carbonPerKilometer;
// Getter
int get carbonFootprint => (carbonPerKilometer / passengers).round();
bool get isTwoWheeled => this == Vehicle.bicycle;
@Override
int compareTo(Vehicle other) => carbonFootprint - other.carbonFootprint;
}Code language: Dart (dart)
Dart 3.13 and newer support primary constructors to simplify enhanced enum syntax:
enum Vehicle(
final int tires,
final int passengers,
final int carbonPerKilometer,
) implements Comparable<Vehicle> {
car(4, 5, 400),
bus(6, 50, 800),
bicycle(2, 1, 0);
int get carbonFootprint => (carbonPerKilometer / passengers).round();
bool get isTwoWheeled => this == Vehicle.bicycle;
@Override
int compareTo(Vehicle other) => carbonFootprint - other.carbonFootprint;
}Code language: Dart (dart)
Working with enums
Access enum constants the same way you access static variables:
final favoriteColor = Color.blue;
if (favoriteColor == Color.blue) {
print('Your favorite color is blue!');
}Code language: Dart (dart)
The index property
Each enum constant comes with an index property returning its zero-based ordinal position inside the enum declaration:
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);Code language: Dart (dart)
Static values constant
Use EnumName.values to retrieve a list containing all enum entries:
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);Code language: Dart (dart)
Switch statements with enums
When using enums inside a switch block, the compiler emits warnings if you fail to cover all enum cases. You can add a default clause as fallback.
var aColor = Color.blue;
switch (aColor) {
case Color.red:
print('Red as roses!');
case Color.green:
print('Green as grass!');
default:
print(aColor); // Color.blue
}Code language: Dart (dart)
The name property
Call .name to obtain the string name corresponding to an enum constant:
print(Color.blue.name); // Outputs "blue"Code language: Dart (dart)
Access custom enum members
Enhanced enums allow you to access custom fields, getters and methods like ordinary objects:
print(Vehicle.car.carbonFootprint);Code language: CSS (css)
Below is a complete sample for this lesson. We will build an enum class for months that puts all knowledge above into practice.
enum Month implements Comparable<Month> {
january(1, '一月', days: 31),
february(2, '二月', days: 28),
march(3, '三月', days: 31),
april(4, '四月', days: 30),
may(5, '五月', days: 31),
june(6, '六月', days: 30),
july(7, '七月', days: 31),
august(8, '八月', days: 31),
september(9, '九月', days: 30),
october(10, '十月', days: 31),
november(11, '十一月', days: 30),
december(12, '十二月', days: 31);
const Month(this.monthNumber, this.cnName, {required this.days});
/// Gregorian calendar month number 1~12
final int monthNumber;
/// Name
final String cnName;
/// Days in common year
final int days;
/// Getter: Check if within Q1
bool get isFirstQuarter => monthNumber <= 3;
/// Getter: Check if month has 31 days
bool get has31Days => days == 31;
/// Custom method: Detect leap year February
bool isLeapYearFebruary(int year) {
if (this != Month.february) return false;
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
/// Implement Comparable for sorting
@Override
int compareTo(Month other) {
return monthNumber - other.monthNumber;
}
}
void main() {
// 1. Basic access to enum constants
Month current = Month.august;
print('Current enum: $current');
print('Enum name property: ${current.name}');
print('Month: ${current.cnName}');
print('Month number 1~12: ${current.monthNumber}');
print('Days in common year: ${current.days}');
print('Is 31-day month: ${current.has31Days}');
print('Belongs to Q1: ${current.isFirstQuarter}');
// 2. index property (zero-based index defined in enum)
print('\n${Month.january.name} index = ${Month.january.index}');
print('${Month.december.name} index = ${Month.december.index}');
// 3. Fetch all enum entries via values
List<Month> allMonths = Month.values;
print('\nTotal ${allMonths.length} months');
// 4. Using enums with switch
print('\n==== switch check ====');
switch (current) {
case Month.january:
print('Start of the year');
case Month.february:
print('May contain leap day');
case Month.march:
case Month.april:
case Month.may:
print('Spring');
case Month.june:
case Month.july:
case Month.august:
print('Summer');
case Month.september:
case Month.october:
case Month.november:
print('Autumn');
case Month.december:
print('End of the year, winter');
}
// 5. Call custom method
Month feb = Month.february;
print('\nLeap February in 2024: ${feb.isLeapYearFebruary(2024)}');
print('Leap February in 2025: ${feb.isLeapYearFebruary(2025)}');
// 6. Enum sorting via Comparable interface
var selected = [Month.october, Month.january, Month.july];
selected.sort();
print('\nSorted months: ${selected.map((m) => m.cnName).toList()}');
}Code language: Dart (dart)
Execution output
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Current enum: Month.august
Enum name property: august
Month: 八月
Month number 1~12: 8
Days in common year: 31
Is 31-day month: true
Belongs to Q1: false
january index = 0
december index = 11
Total 12 months
==== switch check ====
Summer
Leap February in 2024: true
Leap February in 2025: false
Sorted months: [一月, 七月, 十月]Code language: JavaScript (javascript)
Enums