Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add methods or values to enum in dart

Tags:

dart

Starting with Dart 2.6 you can define extensions on classes (Enums included).

enum Cat {
  black,
  white
}

extension CatExtension on Cat {

  String get name {
    switch (this) {
      case Cat.black:
        return 'Mr Black Cat';
      case Cat.white:
        return 'Ms White Cat';
      default:
        return null;
    }
  }

  void talk() {
    print('meow');
  }
}

Example:

Cat cat = Cat.black;
String catName = cat.name;
cat.talk();

Here's one more live example (uses a constant map instead of a switch): https://dartpad.dartlang.org/c4001d907d6a420cafb2bc2c2507f72c


Dart enums are used only for the simplest cases. If you need more powerful or more flexible enums, use classes with static const fields like shown in https://stackoverflow.com/a/15854550/217408

This way you can add whatever you need.


Nope. In Dart, enums can only contain the enumerated items:

enum Color {
  red,
  green,
  blue
}

However, each item in the enum automatically has an index number associated with it:

print(Color.red.index);    // 0
print(Color.green.index);  // 1

You can get the values by their index numbers:

print(Color.values[0] == Color.red);  // True

See: https://www.dartlang.org/guides/language/language-tour#enums


It may not be "Effective Dart" , I add a static method inside a Helper class ( there is no companion object in Dart) .

In your color.dart file

enum Color {
  red,
  green,
  blue
}

class ColorHelper{

  static String getValue(Color color){
    switch(color){
      case Color.red: 
        return "Red";
      case Color.green: 
        return "Green";
      case Color.blue: 
        return "Blue";  
      default:
        return "";
    }
  }

}

Since the method is in the same file as the enum, one import is enough

import 'package:.../color.dart';

...
String colorValue = ColorHelper.getValue(Color.red);

extension is good, but it cannot add static methods. If you want to do something like MyType.parse(string), consider using a class with static const fields instead (as Günter Zöchbauer suggested before).

Here is an example

class PaymentMethod {
  final String string;
  const PaymentMethod._(this.string);

  static const online = PaymentMethod._('online');
  static const transfer = PaymentMethod._('transfer');
  static const cash = PaymentMethod._('cash');

  static const values = [online, transfer, cash];

  static PaymentMethod parse(String value) {
    switch (value) {
      case 'online':
        return PaymentMethod.online;
        break;
      case 'transfer':
        return PaymentMethod.transfer;
        break;
      case 'cash':
        return PaymentMethod.cash;
      default:
        print('got error, invalid payment type $value');
        return null;
    }
  }

  @override
  String toString() {
    return 'PaymentMethod.$string';
  }
}

I found this much handier than using a helper function.

final method = PaymentMethod.parse('online');
assert(method == PaymentMethod.online);

I did this (inspired form the accepted answer by @vovahost)

enum CodeVerifyFlow {
  SignUp, Recovery, Settings
}

extension CatExtension on CodeVerifyFlow {
  String get name {
    return ["sign_up", "recovery", "settings"][index];
  }
}

// use it like
CodeVerifyFlow.SignUp.name

thank me later!


As an improvement on the other suggestions of using Extensions, you can define your assigned values in a list or map, and the extension will be concise.

enum Numbers {
  one,
  two,
  three,
}

// Numbers.one.value == 1

example with list

extension NumbersExtensionList on Numbers {
  static const values = [1, 2, 3];
  int get value => values[this.index];
}

example with map

extension NumbersExtensionMap on Numbers {
  static const valueMap = const {
    Numbers.one: 1,
    Numbers.two: 2,
    Numbers.three: 2,
  };
  int get value => valueMap[this];
}

Note: This approach has the limitation that you can not define a static factory method on the Enum, e.g. Numbers.create(1) (as of Dart 2.9). You can define this method on the NumbersExtension, but it would need to be called like NumbersExtension.create(1)