Haxe ist eine objektorientierte, JavaScript-ähnliche Programmiersprache. Die Möglichkeit, aus Haxe-Code ausführbare Programme für Adobe Flash, JavaScript, PHP, C++ und Neko VM zu erzeugen, zusammen mit leistungsfähigem Remoting (Fähigkeit, Objekte und Methodenaufrufe an andere Systeme zu senden, siehe eigener Abschnitt), machen Haxe ideal für die Programmierung von Webanwendungen, weshalb es auch als universelle weborientierte Sprache bezeichnet wird.

Geschichte Das französische Unternehmen Motion Twin wurde 2001 gegründet und beschäftigt sich seitdem mit der Entwicklung von Flash-basierten Webseiten und Spielen. Die Entwicklung von Haxe ist eng mit der Unternehmensgeschichte verwoben. Als Erfinder von Haxe gilt Nicolas Cannasse, Mitbegründer von Motion Twin.

2003 bis 2005: Tools für die Arbeit mit ActionScript Um sich die Arbeit mit ActionScript zu erleichtern, begann Motion Twin im Dezember 2003 mit der Entwicklung der ActionScriptMetaLanguage. Darin geschriebene Programme werden durch einen eigenen Vorcompiler in gewöhnliches ActionScript umgewandelt. In diesem Schritt wird Typ- und Parameterprüfung zu Compilezeit durchgeführt, wobei auch die weiter unten erläuterte Typinferenz zum Einsatz kommt. Der resultierende ActionScript-Code wird dann mittels des Compilers von Flash in eine SWF-Datei umgewandelt, welche dann beim Nutzer mittels Flash Players angezeigt wird. Zum Vergleich: Ohne den Einsatz der ActionScriptMetaLanguage wird die Typprüfung erst zur Laufzeit möglich, was das Auffinden von Programmfehlern erschwert.

Im April 2004 wurde die ActionScriptMetaLanguage um neue Typen erweitert und nannte sich von da an MotionTypes. Wenig später erhielt der Compiler die Fähigkeit, direkt SWF-Bytecode zu erzeugen, ohne den Umweg über den Macromedia-Compiler zu gehen.

Sowohl ActionScriptMetaLanguage als auch MotionTypes werden nur innerhalb des Unternehmens genutzt. Im Gegensatz dazu wurde MTASC, der MotionTwin Actionscript Compiler im Oktober 2004 als Betaversion der Öffentlichkeit vorgestellt. Dieser Compiler ist unabhängig von MotionTypes, denn er erstellt aus gewöhnlichem ActionScript (welches inzwischen die Sprachversion 2.0 erreicht hatte) SWF-Bytecode. Zusammen mit anderer freier Software ergab sich das Programmpaket FAMES (bestehend aus Flashout, ASDT, MTASC, Eclipse und SwfMill), womit es erstmals möglich war, Flashapplikationen auch ohne die proprietäre Software von Macromedia oder Adobe zu erstellen.

Am 14. Juli 2005, nur zwei Tage nach der öffentlichen Vorstellung des Flash Player 8, unterstützte MTASC bereits diese Flash-Version.

Ab 2005: Aufbau einer eigenen Sprache und Technologie Zunächst wurde geplant, die (ebenfalls von Motion Twin entwickelte) Sprache Neko zukünftig in den Mittelpunkt zu stellen, und Neko mit anderen Technologien, wie z. B. ActionScript 2.0, Java und Ruby, zu kombinieren.

Als seitens Adobe ActionScript 3.0 angekündigt wurde, und die zahlreichen Nutzer von MTASC darauf warteten, dass die neuen Sprachfeatures von MTASC unterstützt würden, kündigte Motion Twin an, die Entwicklung einzustellen und stattdessen die neue Technologie haXe voranzutreiben.

Die Entwicklung begann am 22. Oktober 2005. Nach Alphaversionen im November 2005 und Betaversionen um Februar 2006 folgte am 17. Mai 2006 die Releaseversion 1.0. Die Aktuelle Version ist 4.2.5, welche am 6. März 2022 veröffentlicht wurde. Der Haxe-Compiler ist freie, offene Software unter der GNU General Public License, die mitgelieferten Bibliotheken stehen unter der BSD-Lizenz.

Benennung und Aussprache Der ursprüngliche Name haXe wurde gewählt, weil er dem Autor zufolge „kurz, einfach und cool“ sei und ein X enthält, was, wie er scherzhaft anmerkt, notwendig sei, um eine neue Technologie erfolgreich zu machen.

Es gibt keine offizielle Aussprache des Namens haXe. International verbreitete Aussprachen sind „hex“ (welches einer französischen Aussprache nahekommen soll), „häcks“ und „aytch äx“.

Sprache Haxe ist eine eigenständige Programmiersprache, die sich syntaktisch an JavaScript bzw. ActionScript und Java anlehnt, jedoch auch eigene Syntaxelemente einführt.

Syntaxübersicht Das folgende Codebeispiel bietet einen Überblick über den typischen Aufbau einer Haxe-Quelltextdatei. Dabei zeigt es auch einige fortgeschrittene Möglichkeiten, die vom Programmierer nicht zwingend beherrscht werden müssen: package my.pack;

import flash.Lib;

/** Dokumentation im Javadoc-Stil */ class MyClass<EinTyp> extends MyOtherClass, implements MyInterface {

private var id : Int; private static var idCounter : Int;

public var typisierteVariable : EinTyp;

// Es folgt eine Eigenschaft samt get- und set-Methode. // Der Typ der Eigenschaft wird als Typenparameter angegeben. public var x(getX,setX) : EinTyp; private var my_x : EinTyp;

private function getX() { return my_x;

private function setX( v : EinTyp) { my_x = v; trace("Wert von x wurde geändert!"); return my_x;

/** Dies ist ein Konstruktor */ public function new()

id = idCounter++;

function foo() : Void { for(x in 3...7) trace("Eine Zahl " + x);

/** Einsprungpunkt für die Anwendung */ static function main()

var instanz = new MyClass<Bool>(); instanz.x = true; // ruft den setter auf, welcher eine Warnung per trace ausgeben wird

An dieser Stelle sei nochmal betont, dass dieser Code ohne Änderungen in allen drei Compiler-Zielen lauffähig ist.

Feature-Übersicht

Die meisten der folgenden Haxe-Features sind auch aus weit verbreiteten objektorientierten Sprachen wie C++ oder Java bekannt und werden daher nicht näher erläutert: Strukturierung großer Projekte mittels packages Dokumentation mittels speziellen, Javadoc-ähnlichen Kommentaren Klassen mit Typparametern, wobei neuere Versionen Template-ähnliche Vorzüge bieten Einfachvererbung und das Implementieren von (auch mehreren) Interfaces Zugriffsmodifikatoren wie z. B. private und static Eigenschaften, deren Zuweisung über Zugriffsfunktionen (Getter und Setter) abgewickelt wird Konstruktoren und Destruktoren Main-Methode muss auch innerhalb einer Klasse untergebracht sein For-Each-Schleife (andere Formen der For-Schleife gibt es in Haxe nicht) Iteratoren (im Codebeispiel nicht gezeigt) Reflection (im Codebeispiel nicht gezeigt)

Folgende Features, die viele gängige Sprachen bieten, fehlen jedoch in Haxe: Methodenüberladung Mehrfachvererbung Abstrakte Klassen

Typinferenz Programmiersprachen sind für gewöhnlich statisch oder dynamisch typisiert. Bei statischer Typisierung ist jeder Variable, jedem Attribut und jedem Parameter eindeutig ein Typ zuzuordnen, der zur Laufzeit konstant bleibt. // Java-Beispiel (Java ist statisch typisiert): int x; x = 3; // geht x = "hallo"; // geht nicht

In einer dynamisch typisierten Sprache haben Variablen, Attribute und Parameter keinen klar definierten Typ: // Javascript-Beispiel (Javascript ist dynamisch typisiert): var x; x = 3; // geht x = "hallo"; // geht

Haxe verbindet beide Ansätze. Zum einen ist es dem Programmierer freigestellt, ob der Typ einer Variablen angegeben wird, oder nicht. Zum anderen schlussfolgert (Inferenz bedeutet Schlussfolgerung) der Compiler selbständig den Typ jeder Variable, die nicht vom Programmierer festgelegt wurde, und behandelt sie, als wäre sie statisch typisiert. Als dritte Alternative kann der Programmierer sie explizit als Dynamic deklarieren und somit die Typinferenz aushebeln: // Haxe-Beispiel (in diesem Fall statisch): var x : Int; x = 3; // geht x = "hallo"; // geht nicht

// Haxe-Beispiel (in diesem Fall statisch durch Typinferenz): var x; x = 3; // geht, Compiler schließt darauf, dass x vom Typ 'Int' ist x = "hallo"; // geht nicht

// Haxe-Beispiel (in diesem Fall dynamisch): var x : Dynamic; x = 3; // geht x = "hallo"; // geht

Die Sprachen, für die Haxe einen Ersatz darstellen kann (Javascript, ActionScript, PHP etc.) sind in der Regel dynamisch typisiert. Der Vorteil der Typinferenz sei nochmals an folgendem Beispiel gezeigt: function bar() : Array<Int> { var retval = [1,2,3,4]; if(Math.random() < 0.001) // Math.random() liefert zufälligen Wert zwischen 0 und 1 retval.push(5.001); // ACHTUNG: Diese Zeile erzeugt einen Compiler-Fehler return retval; } Das Array retval ist vom Programmierer nicht typisiert. Jedoch kann der Compiler aus dem Methodenkopf erkennen, dass das Array vom Typ Int sein muss, um später als Rückgabewert zu dienen. Das Einfügen des Wertes 5.001 widerspricht dem, somit wird der Compiler einen Fehler melden. Ohne Typinferenz würde dieser Fehler erst zu Laufzeit auffallen, und auch erst bei Ausführung der markierten Zeile. Aufgrund der if-Bedingung würde dies erst nach ca. 1000 Testläufen auftreten, d. h. eventuell erst, wenn die Software zum Kunden ausgeliefert wurde.

Konditionales Kompilieren Ein Großteil des Haxe-Codes ist auf allen Zielplattformen lauffähig (siehe Abschnitt Zielplattformen). Dennoch kommt man oft nicht um plattformspezifische Anpassungen herum. Diese können wie folgt eingebunden werden: #if flash // haXecode für Flash-Plattform (beliebige Version) // z. B. wird folgendes ein Quadrat mittels eines Flash-MovieClip-Objektes anzeigen: var mc : flash.MovieClip = flash.Lib.current; mc.beginFill(0xFF0000); mc.moveTo(50,50); mc.lineTo(100,50); mc.lineTo(100,100); mc.lineTo(50,100); mc.endFill(); #elseif js // haXecode für Javascript-Plattform // z. B. Zugriff auf das Browser-DOM um etwas anzuzeigen #elseif neko // haXecode für die neko-Plattform #error // wird automatisch den Fehler "Not implemented on this platform" ausgeben #end

Aufzählungstypen Aufzählungstypen sind eine Schlüsselfunktion der Sprache. Sie können selbst Parameter haben und rekursiv sein, was ihnen erlaubt, wie Klassen behandelt zu werden. Enums in Haxe sind nicht einfach nur indizierte „magic-numbers“ wie in den meisten Sprachen, sondern sind abstrakter: Sie haben keinen eigenen Wert, aber können instantiiert werden, wie das folgende Beispiel zeigt:

enum Farbe { rot; gruen; blau; rgb: ( r : Int, g : Int, b : Int );

class Farben { static function nachInt( c : Farbe ) : Int { return switch( c ) { case rot: 0xFF000; case gruen: 0x00FF00; case blau: 0x0000FF; case rgb(r,g,b): (r << 16) | (g << 8) | b;

static function gueltigeAufrufe() { var rotint = nachInt(rot); var rgbint = nachInt(rgb(100,100,100));

(Aus der Haxe-Referenz, modifiziert)

Weitere Details Funktionsparameter können in Haxe sehr genau definiert werden: function mehrereParameter(dreidimensionalsArray : Array<Array<Array<Int>>>, stringval : String, boolval : Bool) {} function optionalerParameter( ?i : Int ) : Int {return 0;} // optional int value returning an int function funktionAlsParameter( f : Void -> Void ) {f();} // call a function with no parameters function eineAndereFunktionAlsParameter( f : Int -> Int ) {var result = f(1);} // call a function that returns an int, with an int parameter function kannAllesMoeglicheSein(d : Dynamic) : Dynamic {return d;} // function which takes any kind of type and returns it

Zielplattformen In Haxe geschriebener Code wird kompiliert. Dabei kann man zwischen folgenden Zielen wählen: Flash, genauer: SWF-Bytecode für AVM 1 (entspricht Flash 6, 7, 8) SWF-Bytecode für AVM 2 (entspricht Flash 9) ActionScript 3.0 Sourcecode JavaScript Neko VM C++ (ab Version 2.04) PHP (ab Version 2.0) Java Bytecode C# Bytecode (experimentell)

Das ansonsten eher unbekannte Neko verdient hierbei besondere Beachtung: Es kann einerseits serverseitig eingesetzt werden (als Standalone-Server oder als Apache-Modul modneko). Andererseits kann es auch direkt beim Client eingesetzt werden. Dazu muss dieser die Neko-VM auf seinem Rechner installieren. Mittels Screenweaver HX ist es möglich, Desktopanwendungen mittels Haxe umzusetzen, bei denen die Logik in Neko umgesetzt ist, das Userinterface jedoch mittels Flash.