Usually, the Haxe Compiler generates only a single class or function even if it has type parameters. This results in a natural abstraction where the code generator for the target language must assume that a type parameter could be of any type. The generated code might then have to perform type checks which can be detrimental for performance.
A class or function can be made generic by attributing it with the @:generic
metadata. This causes the compiler to emit a distinct class or function per type parameter combination with mangled names. A specification like this can yield a boost in sections of performance-critical code on static targets at the cost of a larger output size:
@:generic class MyValue<T> { public var value:T; public function new(value:T) { this.value = value; } } class Main { static public function main() { var a = new MyValue<String>("Hello"); var b = new MyValue<Int>(42); } }
It may seem unusual to see the explicit type MyValue<String>
here as type inference often handles similar situations. Nonetheless, it is required in this case as the compiler must know the exact type of a generic class upon construction. The JavaScript output shows the result:
(function () { "use strict"; var Test = function() { }; Test.main = function() { var a = new MyValue_String("Hello"); var b = new MyValue_Int(5); }; var MyValue_Int = function(value) { this.value = value; }; var MyValue_String = function(value) { this.value = value; }; Test.main(); })();
We can identify that MyValue<String>
and MyValue<Int>
have become MyValue_String
and MyValue_Int
respectively. The situation is similar for generic functions:
class Main { static public function main() { method("foo"); method(1); } @:generic static function method<T>(t:T) {} }
Again, the JavaScript output makes it obvious:
(function () { "use strict"; var Main = function() { } Main.method_Int = function(t) { } Main.method_String = function(t) { } Main.main = function() { Main.method_String("foo"); Main.method_Int(1); } Main.main(); })();