0

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?

Michel Feinstein
  • 13,416
  • 16
  • 91
  • 173

1 Answers1

2

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."
  };
cmp
  • 36
  • 2
  • Well, so built_value EnumClass is not as a Java enum, as many say it is. – Michel Feinstein Mar 13 '19 at 16:07
  • Java also doesn't allow you to create new instances; only to associate constant information with existing instances at the time of definition. It's true there doesn't seem to be a precise equivalent in built_value; the closest equivalent would be to define a getter which indexes into a private map, as in my second example. – cmp Mar 16 '19 at 22:54
  • If I remember correctly, in Java we can pass variables at the time of creation of an enum and get their values back, but it has been a while I did it and I am kinda lazy right now to search about on the docs hahaha anyway, what I did in the end was to create a regular Dart `enum` and pass it to `bulit_value` Value Type class that holds an `enum` and an optional `message`. – Michel Feinstein Mar 16 '19 at 23:05