Dart Enum

Summary: in this tutorial, you’ll learn about Dart enum to manage a fixed number of constant values.

Introduction to the Dart enum type

Enums or enumerated types are special classes representing a fixed number of constant values.

Declaring an enum

To declare a simple enum, you use the enum keyword and list some values you want to be enumerated. For example:

enum Status {
  pending,
  completed,
  rejected,
}Code language: Dart (dart)

By convention, you name the enum using PascalCase in which you capitalize the first character of each word. Also, you use camelCase to name enum values.

Using an enum

To access an enum value, you use the enum name, dot operator, and the value. For example:

var initialStatus = Status.pending;
print(initialStatus);Code language: Dart (dart)

Output:

Status.pendingCode language: Dart (dart)

Each enum value has an index getter that returns the zero-based position of the value in the enum declaration.

For example, in the Status enum, the pending has an index of 0, the completed has an index of 1, and the rejected has an index of 2:

enum Status {
  pending,
  completed,
  rejected,
}

void main() {
  print(Status.pending.index);
  print(Status.completed.index);
  print(Status.rejected.index);
}Code language: Dart (dart)

Output:

0
1
2Code language: Dart (dart)

To get a list of all enumerated values you use the values constants of the enum like this:

enum Status {
  pending,
  completed,
  rejected,
}

void main() {
  List<Status> statuses = Status.values;
  for (var status in statuses) {
    print(status);
  }
}Code language: Dart (dart)

Output:

Status.pending
Status.completed
Status.rejectedCode language: Dart (dart)

To access the name of an enumerated value, you use the .name property. For example:

enum Status {
  pending,
  completed,
  rejected,
}

void main() {
  List<Status> statuses = Status.values;
  for (var status in statuses) {
    print(status.name);
  }
}Code language: Dart (dart)

Output:

pending
completed
rejectedCode language: Dart (dart)

Using enum in a switch statement

Enums work very well with the switch statement. For example:

enum Status {
  pending,
  completed,
  rejected,
}

void main() {
  var status = Status.completed;

  switch (status) {
    case Status.pending:
      print('The request is pending');
      break;
    case Status.completed:
      print('The request completed successfully.');
      break;
    case Status.rejected:
      print('The request faield.');
      break;
  }
}Code language: Dart (dart)

Notice that if you don’t handle all of the enumerated values, you’ll get a warning. For example:

enum Status {
  pending,
  completed,
  rejected,
}

void main() {
  var status = Status.completed;

  switch (status) {
    case Status.completed:
      print('The request completed successfully.');
      break;
    case Status.rejected:
      print('The request faield.');
      break;
  }
}Code language: Dart (dart)

Warning:

Missing case clause for 'pending'.
Try adding a case clause for the missing constant, or adding a defaultCode language: Dart (dart)

Enum class

All enums automatically extend the Enum class. Also, you cannot subclass, implement or mix in, or create a new instance of an enum. For example:

enum Status { pending, completed, rejected }

void main() {
  var status = Status.completed;
  print(status is Enum); // true
}Code language: Dart (dart)

Enhanced enums

Suppose that you have an enum called OrderStatus:

enum OrderStatus {
  open,
  confirmed,
  completed,
  cancelled,
}Code language: Dart (dart)

and you want to compare an instance of the OrderStatus with others like this:

var status = OrderStatus.open;
if (status < OrderStatus.completed) {
  //...
}Code language: Dart (dart)

You’ll get an error:

The operator '<' isn't defined for the type 'OrderStatus'.Code language: Dart (dart)

To resolve this, you need to use enhanced enums. Like classes, you can define fields, methods, and const constructors with the following rules:

  • Instance variables must be final. They cannot have the name values because it’ll cause a conflict with the autogenerated values getter.
  • Generative constructors must be constant.
  • Factory constructors can only return one of the fixed, known enum instances.
  • Cannot override indexhashCode, the equality operator ==.
  • Declare all instances at the beginning of the enum. An enum must have at least one instance.

Note that Dart has supported enhanced enums since version 2.17.

For example:

enum OrderStatus {
  open(10),
  confirmed(20),
  completed(30),
  cancelled(40);

  final int progress;
  const OrderStatus(this.progress);

  bool operator <(OrderStatus status) => progress < status.progress;
  bool operator >(OrderStatus status) => progress > status.progress;
}

void main() {
  var status = OrderStatus.open;
  if (status < OrderStatus.completed) {
    print('The order has not completed');
  }
}Code language: Dart (dart)

How it works.

First, define the progress as a final instance variable. By rule, it must be final:

final int progress;Code language: Dart (dart)

Next, initialize the progress instance variable in the const constructor:

const OrderStatus(this.progress);Code language: Dart (dart)

Then, declare constant values and initialize them with different progress values:

open(10),
confirmed(20),
completed(30),
cancelled(40);Code language: Dart (dart)

After that, override the less than and greater than operators. In these methods, we compare the progress of one enum with another:

bool operator <(OrderStatus status) => progress < status.progress;
bool operator >(OrderStatus status) => progress > status.progress;Code language: Dart (dart)

Finally, use the less-than operator (<) to compare values of the OrderStatus enum:

void main() {
  var status = OrderStatus.open;
  if (status < OrderStatus.completed) {
    print('The order has not completed');
  }
}Code language: Dart (dart)

Summary

  • Use enum type to manage a fixed number of constants.
Was this tutorial helpful ?