Dart Lesson 52 of 102 3 min read
Enums in Dart: Simple and Enhanced Enumerations
Learn enums in Dart: define a fixed set of values, use them in switch, and add fields, methods and constructors with enhanced enums.
On this page
An enum (enumeration) is a type with a small, fixed set of possible values. Use one whenever a variable should only ever be one of a few named options: the days of the week, the state of an order, the size of a T-shirt.
Why not strings? #
With String status = 'shiped'; the typo compiles and fails silently. With an enum, a misspelt value is a compile error and autocomplete lists every option.
A simple enum #
enum OrderStatus { pending, paid, shipped, delivered, cancelled }
void main() {
var status = OrderStatus.shipped;
print(status);
print(status.name); // the name as a String
print(status.index); // position, starting at 0
print(status == OrderStatus.shipped);
}
OrderStatus.shipped
shipped
2
true
All the values #
enum Size { small, medium, large }
void main() {
print(Size.values);
for (final size in Size.values) {
print('${size.index}: ${size.name}');
}
// From a String back to an enum value.
var chosen = Size.values.byName('medium');
print(chosen);
}
[Size.small, Size.medium, Size.large]
0: small
1: medium
2: large
Size.medium
byName throws if the name does not exist. For untrusted text, search safely with Size.values.where((s) => s.name == text).firstOrNull.
Enums and switch #
Dart checks that a switch on an enum handles every value. If you add a new value later, every switch that forgot it stops compiling, which is exactly what you want.
enum Light { red, yellow, green }
String action(Light light) => switch (light) {
Light.red => 'Stop',
Light.yellow => 'Slow down',
Light.green => 'Go',
};
void main() {
print(action(Light.yellow));
}
Slow down
Enhanced enums: fields, constructors and methods #
An enum can carry data and behaviour, like a small class. Each value calls the constructor with its own arguments.
enum Planet {
mercury(diameterKm: 4879, moons: 0),
earth(diameterKm: 12742, moons: 1),
jupiter(diameterKm: 139820, moons: 95);
const Planet({required this.diameterKm, required this.moons});
final int diameterKm;
final int moons;
bool get hasMoons => moons > 0;
String describe() => '$name: $diameterKm km across, $moons moon(s)';
}
void main() {
print(Planet.earth.describe());
print(Planet.mercury.hasMoons);
var biggest = Planet.values.reduce(
(a, b) => a.diameterKm > b.diameterKm ? a : b,
);
print(biggest.name);
}
earth: 12742 km across, 1 moon(s)
false
jupiter
The rules for enhanced enums:
- List the values first, and end the list with a semicolon.
- The constructor must be
const, and all fields must befinal. - You cannot create new values at run time.
A practical example #
enum Plan {
free('Free', 0, 1),
pro('Pro', 499, 10),
team('Team', 1999, 100);
const Plan(this.label, this.pricePerMonth, this.maxProjects);
final String label;
final int pricePerMonth;
final int maxProjects;
bool canCreate(int currentProjects) => currentProjects < maxProjects;
}
void main() {
var plan = Plan.free;
print('${plan.label}: Rs. ${plan.pricePerMonth}/month');
print(plan.canCreate(1));
print(Plan.pro.canCreate(1));
}
Free: Rs. 0/month
false
true
Enums can implement interfaces and use mixins #
abstract class HasCode {
String get code;
}
enum Currency implements HasCode {
npr('NPR'),
usd('USD');
const Currency(this.code);
@override
final String code;
}
void main() => print(Currency.npr.code);
NPR
Tips #
- Name the enum in
UpperCamelCaseand its values inlowerCamelCase. - Do not store
indexin a database or file. Reordering the values would change every number. Storenameinstead. - An enum is ideal for a closed list of simple options. When each option needs its own different data, use a sealed class.
Try it yourself #
Create a Weekday enum with a field isWeekend. Add a getter shortName that returns the first three letters in upper case. Loop over all values and print only the weekdays that are not weekend days.