2.7.5 Enum abstracts

since Haxe 3.1.0

By adding the @:enum metadata to an abstract definition, that abstract can be used to define finite value sets:

@:enum
abstract HttpStatus(Int) {
  var NotFound = 404;
  var MethodNotAllowed = 405;
}

class Main {
  static public function main() {
    var status = HttpStatus.NotFound;
    var msg = printStatus(status);
  }

  static function printStatus(status:HttpStatus) {
    return switch (status) {
      case NotFound:
        "Not found";
      case MethodNotAllowed:
        "Method not allowed";
    }
  }
}

The Haxe Compiler replaces all field access to the HttpStatus abstract with their values, as evident in the JavaScript output:

Main.main = function() {
    var status = 404;
    var msg = Main.printStatus(status);
};
Main.printStatus = function(status) {
    switch(status) {
    case 404:
        return "Not found";
    case 405:
        return "Method not allowed";
    }
};

This is similar to accessing variables declared as inline, but has several advantages:

  • The typer can ensure that all values of the set are typed correctly.
  • The pattern matcher checks for exhaustiveness when matching an enum abstract.
  • Defining fields requires less syntax.
since Haxe 4.0.0

Enum abstracts can be declared without using the @:enum metadata, instead using the more natural syntax enum abstract. Additionally, if the underlying type is String or Int, the values for the enum cases can be omitted and are deduced by the compiler:

  • For Int abstracts, the deduced values increment the last user-defined value or start at zero if no value was declared yet.
  • For String abstracts, the deduced value is the identifier of the enum case.
enum abstract Numeric(Int) {
  var Zero; // implicit value: 0
  var Ten = 10;
  var Eleven; // implicit value: 11
}

enum abstract Textual(String) {
  var FirstCase; // implicit value: "FirstCase"
  var AnotherCase; // implicit value: "AnotherCase"
}