ActionScript 3 ist eine vollständig objektorientierte Programmiersprache. Alle Typen, selbst die Basisklassen, sind als Klassen implementiert.
Variablen sollten typisiert werden, dies hat direkt mehrere Vorteile. Einerseits kann der Compiler direkt bei der Programmübersetzung schauen ob die richtige Variable übergeben wird, oder ob die Methode auf der Klasse verfügbar ist, und zur Laufzeit muss die virtuelle Maschine nicht überprüfen welche Methoden grade zur Verfügung stehen, also ein Geschwindigkeitsvorteil bei der Entwicklung und zur Laufzeit. Wer trotzdem eine untypisierte Variable braucht kann diese mit der Varaiblendeklaration "var myVar:*;" erzeugen.
Um eine Variable einem anderen Datentyp zu zuweisen, zB. eine untypisierte Variable zu einer typisierten Variable zu überführen, oder ein Parameter Objekt auf einem bestimmten Datentyp zu überführen, bietet ActionScript 3 zwei verschiedene Methoden an. Einerseits das casten per Konstruktor Aufruf oder das casten mit dem Befehl as. Beide Varianten erzeugen unterschiedliche Ergebnisse und haben daher beide Vor- und Nachteile.
// Datentyp casting var myUntypedVar:* = "Hallo Welt"; // casten wir diese Variable auf den Typ String var myString1:String = String(myUntypedVar); trace("Casted with String(): '" + myString1 + "'"); // 'Hallo Welt' var myString2:String = myUntypedVar as String; trace ("Casted as String: '" + myString2 + "'"); // 'Hallo Welt' // casten wir diese Variable auf den Typ Number var myNUmber1:Number = Number(myUntypedVar); trace ("Casted with Number(): '" + myNumber1 + "'"); // 'NaN' var myNumber2:Number = myUntypedVar as Number; trace ("Casted as Number: '" + myNumber2 + "'"); // '0' // casten wir diese Variable auf den Typ Array var myArray1:Array = Array(myUntypedVar); trace ("Casted with Array(): '" + myArray1 + "'"); // 'Hallo Welt' var myArray2:Array = myUntypedVar as Array; trace ("Casted as Array: '" + myArray2 + "'"); // 'null'
Man erkennt die Unterschiede in den Ergebnissen. Überraschen mag der Wert 'Hallo Welt' bei der Cast Methode mit Array(), aber da dieser Aufruf auch zum erstellen eines neuen Array genutzt wird, wird dort einfach ein Array mit dem ersten Element 'Hallo Welt' erstellt. Das Casten mit as bietet den Vorteil das es im Fehlerfall als Ergebnis immer mit einem Wert belegt ist, der in einem if-statement als false ausgewertet wird und weder die Verwechslung des Array Beispiel auftreten kann, noch ein Vergleich zu NaN nötig wird.
Klassen werden in Packages definiert. Pro Datei kann nur eine Klasse definiert werden. Jede Klasse kann nur eine andere Klasse erweitern.
package { import flash.display.Sprite; // Anzeigecontainer ohne Zeitleiste import flash.text.TextField; // Textfeld // Sprite erweitern mit unserer Klasse 'HelloWorld' public class HelloWorld extends Sprite { public function HelloWorld() { var txt:TextField = new TextField(); txt.width = 200; txt.x = 200; txt.y = 200; txt.text = "Hello World"; addChild(txt); } } }
Interfaces können mit implements eingebunden werden
Um die Zugehörigkeit einer Klasse zu einer anderen festzustellen verwendet man den is Operator. Dieser liefert true zurück wenn Klasse A & Klasse B das gleiche Objekt sind, Klasse A Klasse B erweitert (extends), Klasse A Klasse B implementiert (implements) und wenn Klasse A eine Kombination aus den genannten Möglichkeiten ist. Der instanceof Operator ist in ActionScript 3 veraltet und bei Objekten die mittels Prototyping erstellt worden sind anzuwenden.
Die Ereignisbehandlung ist grundlegend umgebaut worden und bietet nun ein flexibles merphasiges Eventmodell, dass auf dem DOM Level 3 Standard basiert.
Alle Klassen, die das Interface 'IEventDispatcher' implementieren können Ereignisse abonnieren. Mit dem Methodenaufruf 'object.addEventListener(eventName, EventMethod)' installiert man den Ereignishandler. Die Behandlungsmethode wird nicht im Event erzeugendem object selbst, sondern in der Umgebung, in der auch das object liegt, implementiert. Durch diese Methode wechselt man in der Ereignisbehandlung nicht den Sichtbarkeitsbereich.
Alle Eventmethoden liefern als Parameter ein Objekt von ihrem EventTyp mit, in diesem Objekt steht unter anderem auch das auslösende Objekt.
Alle Eventnamen sind in ActionScript 3 als öffentliche Konstanten der jeweiligen EventKlasse definiert. Dies hat den Vorteil das der Editor alle verfügbaren Events in der Codevervollständigung anbieten kann und der Compiler bei Tippfehler direkt die Übersetzung abbricht.
package { import flash.display.Sprite; // Anzeigecontainer ohne Zeitleiste import flash.text.TextField; // TextFeld public class EventExample { public function EventExample() { var txt:TextField = new TextField(); txt.width = 200; txt.height = 100; txt.boder = true; txt.text = "Klick mich"; txt.addEventListener(MouseEvent.CLICK, onClicked); addChild(txt); } public function onClicked(event:MouseEvent):void { if (event.target as TextField) { event.target.text = "Geklickt!"; } } } }
ActionScript 3 bietet auch die Möglichkeit Fehler zu werfen und zu fangen. Alle Fehler gehen auf die Klasse Error zurück. Mit try { … } catch (…) { … } finally { … } werden Fehler gefangen. Mit throw new Error(…); wirft man einen Fehler.
package { public class ExceptionExample { import flash.errors.IllegalOperationError; import flash.errors.IOError; import flash.errors.IOErrorEvent; public function ExceptionExample() {} // hier wird der Fehler gefangen public staic function catch():void { try { var myValue:* = new Array(); trace(myValue.getChildAt(0)); // Spritemethode auf Array Objekt } catch ( error:IOErrorEvent ) { trace ("IOErrorEvent catch: " + error); } catch ( error:TypeError ) { trace ("TypeError catch: " + error); } catch ( error:Error ) { trace ("Error catch: " + error); } finally { trace("that was lucky..."); } } // diese Methode bringt den Compiler zum abbruch public static function noCatch():void { var myValue:Array = new Array(); trace ( myValue.getChildAt(0)); }
Die virtuelle Maschine hinter ActionScript 3 ist von grund auf neu entwickelt worden, immer mit dem Ziel die größtmögliche Geschwindigkeit zu erreichen. Für dieses Ziel wurde auf die Abwärtskompatibilität verzichtet und der Flashplayer 9 bringt beide virtuellen Maschinen mit: AVM1 für AS1/AS2 Code und die AVM2 für AS3 Code.
Eine Just-In-Time-Kompilierung erstellt zur Laufzeit Profile der Anwendung und kann häufig genutze Codeabschnitte in nativen Code übersetzten, der dann nicht mehr interpretiert werden muss und so wesentlich schneller abgearbeitet werden kann.
Ausserdem bringt die AVM2 eine Garbage Collection mit, die Objekte auf die keine (starke) Referenz mehr besteht aus dem Speicher entfernt. Starke Referenzen sind der Regelfall. Beim Datentyp Dictionary ist es möglich auch Objekte als Indizierungsschlüssel zu verwenden. Wenn man bei der Erstellung des Dictionary aber den Parameter weak mit true belegt, werden als Schlüssel weiche Referenzen genutzt. Wird das Objekt nur noch als Index im Dictionary genutzt, wird es auch von der Garbage Collection aufgeräumt.