DART 'ENUMERATION' (Flutter)

DART 'ENUMERATION' (Flutter)

Enumerated types, often called enumerations or enums, are a special kind of class used to represent 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,
}

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);

Output:

Status.pending

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);
}

Output:

0
1
2

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;
  }
}

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;
  }
}

Warning:

Missing case clause for 'pending'.
Try adding a case clause for the missing constant, or adding a default

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
}

Enhanced enums

Suppose that you have an enum called OrderStatus:

enum OrderStatus {
  open,
  confirmed,
  completed,
  cancelled,
}

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

var status = OrderStatus.open;
if (status < OrderStatus.completed) {
  //...
}

You’ll get an error:

The operator '<' isn't defined for the type 'OrderStatus'.

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 index, hashCode, 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');
  }
}

How it works.

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

final int progress;

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

const OrderStatus(this.progress);

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

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

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;

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');
  }
}

Summary

  • Use enum type to manage a fixed number of constants.

THANK YOU!