Constants in Haxe

For non-static variables and objects, you can give them shallow constness as shown below:

public var MAX_COUNT(default, never):Int = 100;

This means you can read the value in the 'default' way but can 'never' write to it.

More info can be found http://adireddy.github.io/haxe/keywords/never-inline-keywords.


The usual way to declare a constant in Haxe is using the static and inline modifiers.

class Main {
    public static inline var Constant = 1;

    static function main() {
        trace(Constant);
        trace(Test.Constant);
    }
}

If you have a group of related constants, it can often make sense to use an enum abstract. Values of enum abstracts are static and inline implicitly.


Note that only the basic types (Int, Float, Bool) as well as String are allowed to be inline, for others it will fail with this error:

Inline variable initialization must be a constant value

Luckily, Haxe 4 has introduced a final keyword which can be useful for such cases:

public static final Regex = ~/regex/;

However, final only prevents reassignment, it doesn't make the type immutable. So it would still be possible to add or remove values from something like static final Values = [1, 2, 3];.

For the specific case of arrays, Haxe 4 introduces haxe.ds.ReadOnlyArray which allows for "constant" lists (assuming you don't work around it using casts or reflection):

public static final Values:haxe.ds.ReadOnlyArray<Int> = [1, 2, 3];
Values = []; // Cannot access field or identifier Values for writing
Values.push(0); // haxe.ds.ReadOnlyArray<Int> has no field push

Even though this is an array-specific solution, the same approach can be applied to other types as well. ReadOnlyArray<T> is simply an abstract type that creates a read-only "view" by doing the following:

  • it wraps Array<T>
  • it uses @:forward to only expose fields that don't mutate the array, such as length and map()
  • it allows implicit casts from Array<T>

You can see how it's implemented here.

Tags:

Haxe