2

I'm using the style class below to mimick enums (from Does Dart support enumerations?) It is working fine in that this snippet produces expected results.

void main() {
  InterpolationType it = InterpolationType.LINEAR;
  print("it is $it and stringified ${stringify(it)}");
  print(InterpolationType.fromJson(it.toJson()));
}

But the DartEditor is complaining about "Expected constant expression" in the case statements of fromJson method. Is there a const I can throw in somewhere to get rid of this complaint?

class InterpolationType { 
  static const LINEAR = const InterpolationType._(0);
  static const STEP = const InterpolationType._(1);
  static const CUBIC = const InterpolationType._(2);

  static get values => [
    LINEAR,
    STEP,
    CUBIC
  ];

  final int value;

  const InterpolationType._(this.value);

  String toString() { 
    switch(this) { 
      case LINEAR: return "LINEAR";
      case STEP: return "STEP";
      case CUBIC: return "CUBIC";
    }
  }

  int toJson() { 
    return this.value;
  }

  static InterpolationType fromJson(int v) { 
    switch(v) { 
      case LINEAR.value: return LINEAR;
      case STEP.value: return STEP;
      case CUBIC.value: return CUBIC;
    }
  }

  static InterpolationType fromString(String s) { 
    switch(s) { 
      case "LINEAR": return LINEAR;
      case "STEP": return STEP;
      case "CUBIC": return CUBIC;
    }
  }
}
Community
  • 1
  • 1
user1338952
  • 3,233
  • 2
  • 27
  • 41

1 Answers1

4

As you discovered: accessing fields from a const object is not a constant operation. So the editor (as well as the VM and dart2js) are right.

With the current syntax there is no way to express a (informal) contract that a field of a class will always be a final field. For example, I could change the value-field to be a getter instead of a field. The interface-contract of the class definitely allows me to do that, because I never told anybody that I would keep "value" as a field. However if I did that it would break every program that relied on the existence of this final field.

As a consequence the current behavior is very unlikely to change.

However: in theory it would be possible to improve the Dart language so that you could use "const" instead of "final" for local fields, and initialize them with initializer lists. And in this case accessing the field could be considered a constant operation. I currently don't see any downsides to this behavior and it would be backwards-compatible.

// WARNING: What follows DOES NOT WORK, just a potential example
class InterpolationType {
  const value;  // Note the "const" instead of "final".
  const InterpolationType._(this.value);
}

The language is already pretty stable but you can open a bug at http://dartbug.com/ and suggest this behavior. It's not very likely that the feature-request would be accepted, but it's definitely worth a try.

Seth Ladd
  • 112,095
  • 66
  • 196
  • 279
Florian Loitsch
  • 7,698
  • 25
  • 30
  • If I understand, the suggestion is change 'final int value' to 'const value'. Doing this to the above example gives: Error: line 15 pos 9: const field 'value' must have an initializer expression – user1338952 Mar 30 '13 at 15:38
  • Correct. This behavior doesn't exist yet. You can suggest it as a feature-request for the language. (Reworded answer to make this clear). – Florian Loitsch Mar 30 '13 at 21:30