Enum type in Dart

Introduction

Enums used to represent a fixed number of constant values. They are a helpful way to model a set of related constants in a type-safe way. Using enums can make your code more readable and maintainable by providing meaningful names for these values.

Basic usage of Enum

enum Status {
  none,
  running,
  stopped,
  paused
}

Accessing Enum Values

var currentStatus = Status.running;

Using Enums in Switch Statements

switch (currentStatus) {
  case Status.none:
    print('No operation is currently running.');
    break;
  case Status.running:
    print('Operation is running.');
    break;
  case Status.stopped:
    print('Operation has stopped.');
    break;
  case Status.paused:
    print('Operation is paused.');
    break;
}

Enum Values and Iteration

for (var status in Status.values) {
  print('Status: $status, Index: ${status.index}');
}

Enum Enhancements

The ability to add methods, getters, constructors, and fields directly within the enum declaration.

enum UserRole {
  admin,
  editor,
  viewer;

  // Add a field to an enum
  final int permissionLevel;

  // Enum constructor
  const UserRole() : permissionLevel = _setPermissionLevel();

  // Static method to determine permission level
  static int _setPermissionLevel() {
    switch (this) {
      case UserRole.admin:
        return 3;
      case UserRole.editor:
        return 2;
      case UserRole.viewer:
        return 1;
    }
  }

  // Example of a method
  bool canEditContent() {
    return this == UserRole.admin || this == UserRole.editor;
  }

  // Example of a getter
  String get description {
    switch (this) {
      case UserRole.admin:
        return "Can access and modify all content and settings.";
      case UserRole.editor:
        return "Can access and modify content.";
      case UserRole.viewer:
        return "Can view content.";
    }
  }

  // Factory constructor for creating an enum from a string
  static UserRole? fromString(String roleAsString) {
    for (var role in UserRole.values) {
      if (role.toString().split('.').last == roleAsString) {
        return role;
      }
    }
    return null; // Return null or throw an exception if the string doesn't match
  }
}

they do not support factory constructors in the same way classes do. Factory constructors are typically used in classes to control the instantiation process, which can involve returning instances of a class from a cache, creating instances of subtypes, or performing other custom instantiation logic.

The concept of a factory constructor doesn't directly apply to enums because you're not creating new instances in the way you might with a class.

enum TaskStatus {
  pending(progressValue: 0),
  inProgress(progressValue: 50),
  done(progressValue: 100);

  final int progressValue;
  const TaskStatus({required this.progressValue});

  static TaskStatus fromProgress(int progress) {
    if (progress <= 0) {
      return TaskStatus.pending;
    } else if (progress < 100) {
      return TaskStatus.inProgress;
    } else {
      return TaskStatus.done;
    }
  }
}
void main() {
  int progress = 75; // Example progress value
  TaskStatus status = TaskStatus.fromProgress(progress);

  print('With progress at $progress%, the task is ${status.toString().split('.').last}.');
  // Output: With progress at 75%, the task is inProgress.
}