Search code examples
dartcode-generationbuilt-value

How to define fields in a built_value EnumClass?


I wanted to have a EnumClass with an optional message field, something like this:

class Status extends EnumClass {
  static const Status error = _$error;
  static const Status completed = _$completed;

  String message;

  const Status._(String name) : super(name);

  static BuiltSet<Status> get values => _$values;
  static Status valueOf(String name) => _$valueOf(name);
}

The problem is I get this error message:

Can't define a const constructor for a class with non-final fields.

And if I declare message as final, then I can't initialize it, since the constructor is hidden.

Is there a way to achieve this? Maybe make a generated Enum Builder?


Solution

  • The purpose of an "enum type" is to create a predefined set of values. If you were to allow clients to create new instances of Status, even const ones, that property would no longer hold; the valueOf() method would throw an exception if passed such an instance, and values would not contain it. So this violates the contract of an "enum type".

      // BAD: no longer an "enum type" if clients can create new instances
      const Status.withMessage(String name, String message)
        : message = message, super(name);
    

    On the other hand, if the message is constant per enum value and not intended to be provided by clients, you can simply add a getter to the class:

      // GOOD: Adding new methods, getters, or const-initialized member variables is fine.
      String get message =>
          _messages[this] ??
              (throw StateError('No message for Status.$name'));
    
      static const _messages = const {
        error: "An error occurred.",
        completed: "Successfully completed."
      };