Creating Factory Constructors for enums with Dart 2.17's enhanced enums
Introduction
Recently, I’ve been developing a Flutter application personally, and I found myself in a situation where I wanted to generate an enum from a string.
Previously, I defined methods for enums using Extensions. However, remembering that enums were enhanced in Dart 2.17, I researched and found that it was possible to achieve this without Extensions. I wanted to summarize this for personal reference.
Enhanced enums
What are enhanced enums?
First, let’s briefly touch on enhanced enums. Borrowing code from the official page, enhanced enums allow you to define instance variables, methods, and constructors within the enum itself, as shown below:
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;
int get carbonFootprint => (carbonPerKilometer / passengers).round();
@override
int compareTo(Vehicle other) => carbonFootprint - other.carbonFootprint;
}
However, there are some constraints:
- Instance variables must be
final
. Generative constructors
must beconst
.- Factory constructors must return a defined enum (cannot return
null
). - Extending other classes is not allowed.
- Overriding
index
,hashCode
, or==
is not possible. - Members named
values
cannot be defined (to avoid conflict with auto-generated members by enum). - At least one instance must be defined at the beginning of the declaration.
Factory Constructor
While the official page doesn’t provide an example, Factory constructors can also be defined:
enum Color {
red,
blue,
none; // Note the semicolon!
factory Color.from(String value) {
switch (value) {
case 'red':
return Color.red;
case 'blue':
return Color.blue;
default:
return Color.none;
}
}
}
Color.from('red') // Returns Color.red
Due to the constraints of enhanced enums, it’s not possible to return null
. Hence, it’s crucial to provide some sort of handling (like throwing an error or returning a dedicated enum) for unexpected arguments.
Conclusion
Enums have become much more convenient with enhanced enums. I look forward to using them more frequently and updating my existing code accordingly.