When wrapping an underlying type, it is sometimes desirable to "keep" parts of its functionality. Because writing forwarding functions by hand is cumbersome, Haxe allows adding the @:forward
metadata to an abstract type:
@:forward(push, pop) abstract MyArray<S>(Array<S>) { public inline function new() { this = []; } } class Main { static public function main() { var myArray = new MyArray(); myArray.push(12); myArray.pop(); // MyArray<Int> has no field length // myArray.length; } }
The MyArray
abstract in this example wraps Array
. Its @:forward
metadata has two arguments which correspond to the field names to be forwarded to the underlying type. In this example, the main
method instantiates MyArray
and accesses its push
and pop
methods. The commented line demonstrates that the length
field is not available.
As usual, we can look at the JavaScript output to see how the code is being generated:
Main.main = function() { var myArray = []; myArray.push(12); myArray.pop(); };
@:forward
can be utilized without any arguments in order to forward all fields. Of course, the Haxe Compiler still ensures that the field actually exists on the underlying type.
Trivia: Implemented as macro
Both the
@:enum
and@:forward
functionality were originally implemented using build macros. While this worked nicely in non-macro code, it caused issues if these features were used from within macros. The implementation was subsequently moved to the compiler.