Flash CS3-Dokumentation |
|||
| Programmieren mit ActionScript 3.0 > Objektorientierte Programmierung mit ActionScript > Weiterführende Themen | |||
Dieser Abschnitt beginnt mit einem kurzen Rückblick auf die Geschichte von ActionScript und der OOP und beschreibt dann das ActionScript 3.0-Objektmodell. Es wird beschrieben, wieso die neue ActionScript Virtual Machine (AVM2) wesentlich schneller ausgeführt werden kann als frühere Versionen von Flash Player, welche die alte ActionScript Virtual Machine (AVM1) enthalten.
Da ActionScript 3.0 auf früheren Versionen von ActionScript aufbaut, sind Kenntnisse, wie sich das ActionScript-Objektmodell entwickelt hat, durchaus von Nutzen. ActionScript begann als einfacher Mechanismus zur Skripterstellung für frühe Versionen des Flash-Authoring-Tools. Mit der Zeit begannen Programmierer mit ActionScript zunehmend komplexere Anwendungen zu erstellen. Um den Anforderungen dieser Programmierer zu entsprechen, wurden jeder neuen Version weitere Sprachfunktionen hinzugefügt, die die Erstellung komplexer Anwendungen vereinfachen.
ActionScript 1.0 bezieht sich auf die Version der Sprache, die in Flash Player 6 und früheren Versionen verwendet wurde. Bereits in diesem frühen Entwicklungsstadium basierte das ActionScript-Objektmodell auf dem Konzept eines Objekts als grundlegendem Datentyp. Ein ActionScript-Objekt ist ein zusammengesetzter Datentyp mit einer Reihe von Eigenschaften. Im Sinne eines Objektmodells umfasst der Begriff Eigenschaften alle Elemente, die an ein Objekt angefügt werden können, beispielsweise Variable, Funktionen oder Methoden.
Obwohl diese erste Generation von ActionScript das Definieren von Klassen mit dem Schlüsselwort class noch nicht unterstützte, konnten Sie eine Klasse mit einem Sonderobjekt namens „Prototypobjekt" definieren. Anstelle das Schlüsselwort class zum Erstellen einer abstrakten Klassendefinition zu verwenden, die Sie in konkrete Objekte instanziieren (wie in klassenbasierten Sprachen wie Java und C++), verwenden Sie in prototypbasierten Sprachen wie ActionScript 1.0 ein existierendes Objekt als Modell (oder Prototyp) für andere Objekte. Während Objekte in einer klassenbasierten Sprache auf eine Klasse verweisen können, die als Vorlage dient, verweisen Objekte in einer prototypbasierten Sprache stattdessen auf ein anderes Objekt (ihren Prototyp), der als Vorlage dient.
Zum Erstellen einer Klasse in ActionScript 1.0 definieren Sie eine Konstruktorfunktion für diese Klasse. In ActionScript sind Funktionen tatsächliche Objekte, nicht nur abstrakte Definitionen. Die von Ihnen erstellte Konstruktorfunktion dient als prototypisches Objekt für Instanzen dieser Klasse. Im folgenden Codebeispiel wird eine Klasse namens Shape erstellt und eine Eigenschaft mit der Bezeichnung visible definiert, die standardmäßig auf true gesetzt ist:
// Basisklasse
function Shape() {}
// Erstellt eine Eigenschaft namens „visible".
Shape.prototype.visible = true;
Diese Konstruktorfunktion definiert eine Shape-Klasse, die Sie wie folgt mit dem new-Operator instanziieren können:
myShape = new Shape();
Das Shape()-Konstruktorfunktionsobjekt kann nicht nur als Prototyp für Instanzen der Shape-Klasse dienen, sondern auch als Prototyp für Unterklassen der Shape-Klasse verwendet werden, d. h. für Klassen, die die Shape-Klasse erweitern.
Das Erstellen einer Klasse, bei der es sich um eine Unterklasse der Shape-Klasse handelt, umfasst zwei Schritte. Als Erstes erstellen Sie die Klasse, indem Sie eine Konstruktorfunktion für die Klasse definieren. Dies wird im folgenden Code gezeigt:
// untergeordnete Klasse
function Circle(id, radius)
{
this.id = id;
this.radius = radius;
}
Dann verwenden Sie den new-Operator, um die Shape-Klasse zu deklarieren, die der Prototyp für die Circle-Klasse ist. In der Standardeinstellung verwendet jede von Ihnen erstellte Klasse die Object-Klasse als Prototyp. Das bedeutet, dass Circle.prototype derzeit ein generisches Objekt enthält (eine Instanz der Object-Klasse). Um festzulegen, dass der Circle-Prototyp jetzt „Shape" anstelle von „Object" sein soll, verwenden Sie den folgenden Code. Darin wird der Wert von Circle.prototype so geändert, dass er ein Shape-Objekt anstelle eines generischen Objekts enthält:
// „Circle" zu einer Unterklasse von „Shape" machen. Circle.prototype = new Shape();
Die Shape-Klasse und die Circle-Klasse sind jetzt in einer Vererbungsbeziehung miteinander verknüpft, die allgemein als Prototypkette bezeichnet wird. Im folgenden Diagramm werden die Beziehungen in einer Prototypkette verdeutlicht:
Die Basisklasse am Ende jeder Prototypkette ist die Object-Klasse. Die Object-Klasse enthält eine statische Eigenschaft namens Object.prototype, die auf das Basis-Prototypobjekt für alle Objekte verweist, die in ActionScript 1.0 erstellt wurden. Das nächste Objekt in unserer Beispiel-Prototypkette ist das Shape-Objekt. Der Grund dafür ist, dass die Shape.prototype-Eigenschaft nie explizit eingestellt wurde, daher enthält es noch immer ein generisches Objekt (eine Instanz der Object-Klasse). Der abschließende Link in dieser Kette ist die Circle-Klasse, die mit ihrem Prototyp verknüpft ist (die Circle.prototype-Eigenschaft enthält ein Shape-Objekt).
Wird, wie im folgenden Beispielcode, eine Instanz der Circle-Klasse erstellt, so erbt die Instanz die Prototypkette der Circle-Klasse:
// Eine Instanz der Circle-Klasse erstellen. myCircle = new Circle();
Sie haben bereits eine Eigenschaft namens visible als Mitglied der Shape-Klasse erstellt. In unserem Beispiel existiert die Eigenschaft visible nicht als Teil des myCircle-Objekts, sondern als Mitglied des Shape-Objekts. Daher gibt die folgende Codezeile true zurück:
trace(myCircle.visible); // Ausgabe: true
Flash Player kann sicherstellen, dass das myCircle-Objekt die visible-Eigenschaft erbt, indem es die Prototypkette aufwärts durchläuft. Bei Ausführung dieses Codes sucht Flash Player zunächst in den Eigenschaften des myCircle-Objekts nach einer Eigenschaft namens visible, findet sie jedoch nicht. Als Nächstes sucht Flash Player im Circle.prototype-Objekt, findet eine Eigenschaft namens visible jedoch noch immer nicht. Auf dem weiteren Weg durch die Prototypkette findet Flash Player schließlich die im Objekt Shape.prototype definierte Eigenschaft visible, und gibt den Wert dieser Eigenschaft zurück.
Zur Vereinfachung werden in diesem Abschnitt viele Einzelheiten und Feinheiten der Prototypkette ausgelassen. Stattdessen werden mehr Informationen zum Prinzip des ActionScript 3.0-Objektmodells angeboten.
Mit ActionScript 2.0 wurden neue Schlüsselwörter wie class, extends, public und private, eingeführt, mit denen Klassen so definiert werden konnten, wie es Programmierer mit Kenntnissen von klassenbasierten Sprachen wie Java und C++ gewohnt sind. Der zu Grunde liegende Vererbungsmechanismus hat sich jedoch beim Versionswechsel von ActionScript 1.0 auf ActionScript 2.0 nicht geändert. Mit ActionScript 2.0 wurde lediglich eine neue Syntax zum Definieren von Klassen hinzugefügt. Die Prototypkette ist in beiden Versionen der Programmiersprache identisch.
Mit der neu in ActionScript 2.0 eingeführten Syntax, die in dem folgenden Codeauszug vorgestellt wird, können Sie, wie viele Programmierer bestätigen, Klassen intuitiver definieren:
// Basisklasse
class Shape
{
var visible:Boolean = true;
}
Mit ActionScript 2.0 wurden auch Typanmerkungen für die Typüberprüfung während der Kompilierung eingeführt. Mit diesen Typanmerkungen können Sie deklarieren, dass die Eigenschaft visible aus dem vorangegangenen Beispiel nur einen booleschen Wert enthalten darf. Das neue Schlüsselwort extends vereinfacht darüber hinaus das Erstellen einer Unterklasse. Im folgenden Beispielcode wird ein Prozess, für den in ActionScript 1.0 zwei Schritte erforderlich waren, mithilfe des Schlüsselworts extends in nur einem Schritt abgeschlossen:
// untergeordnete Klasse
class Circle extends Shape
{
var id:Number;
var radius:Number;
function Circle(id, radius)
{
this.id = id;
this.radius = radius;
}
}
Der Konstruktor wird nun als Teil der Klassendefinition deklariert, und die Klasseneigenschaften id und radius müssen ebenfalls explizit deklariert werden.
Darüber hinaus wurde mit ActionScript 2.0 eine Unterstützung für die Definition von Schnittstellen eingefügt. Somit können Sie objektorientierte Programme mit formal definierten Protokollen für die Kommunikation von Objekten untereinander aufwerten.
Ein allgemeines Schema bei der objektorientierten Programmierung, das im Wesentlichen mit Java und C++ in Verbindung gebracht wird, verwendet Klassen zur Definition der Objekttypen. Programmiersprachen, die dieses Schema angenommen haben, neigen dazu, Klassen zum Konstruieren von Instanzen des von der Klasse definierten Datentyps zu verwenden. ActionScript verwendet für beides Klassen, der Ursprung als eine prototypbasierte Sprache fügt jedoch eine weitere interessante Eigenschaft hinzu. ActionScript erstellt für jede Klassendefinition ein spezielles Klassenobjekt, dass das gemeinsame Nutzung von Verhalten und Zustand ermöglicht. Für viele ActionScript-Programmierer hat diese Unterscheidung keine praktischen Auswirkungen. ActionScript 3.0 ist so konzipiert, dass Sie moderne objektorientierte ActionScript-Anwendungen erstellen können, ohne dass Sie diese speziellen Klassenobjekte verwenden oder gar verstehen müssen. Erfahrene Programmierer, die jedoch von den Vorteilen der Klassenobjekte profitieren möchten, finden in diesem Abschnitt weiterführende Informationen.
Das folgende Diagramm zeigt die Struktur eines Klassenobjekts, das eine einfache Klasse namens „A" darstellt, die mit der Anweisung class A {} definiert wurde:
Jedes Rechteck im Diagramm stellt ein Objekt dar. Jedes Objekt im Diagramm hat einen tiefgestellten Buchstaben A, der kennzeichnet, dass es zur Klasse A gehört. Das Klassenobjekt (CA) enthält Verweise auf verschiedene andere wichtige Objekte. Ein Instanz-Traitsobjekt (TA) speichert die Instanzeigenschaften, die in einer Klassendefinition definiert sind. Ein Klassen-Traitsobjekt (TCA) stellt den internen Typ der Klasse dar und speichert die statischen Eigenschaften, die von der Klasse definiert wurden (das tiefgestellte Zeichen C steht für „Class" [Klasse]). Das Prototyp-Objekt (PA) verweist immer auf das Klassenobjekt, an das es ursprünglich über die constructor-Eigenschaft angefügt wurde.
Das neu mit ActionScript 3.0 eingeführte Traitsobjekt wurde zur Performanceverbesserung implementiert. In früheren Versionen von ActionScript konnte das Nachschlagen eines Namens ein sehr zeitaufwendiger Prozess sein, da Flash Player die Prototypkette aufwärts durchlief. Mit ActionScript 3.0 wird die Suche eines Namens sehr viel effizienter und weniger zeitaufwendig durchgeführt, da geerbte Eigenschaften aus den übergeordneten Klassen in die Traitsobjekte der Unterklassen kopiert werden.
Ein direkter Zugriff auf das Traitsobjekt über den Programmcode ist nicht möglich, aber das Vorhandensein ist aufgrund der Performanceverbesserungen und besseren Speichernutzung deutlich spürbar. Das Traitsobjekt stellt der AVM2 ausführliche Informationen zum Layout und Inhalt einer Klasse zur Verfügung. Mit diesen Daten ist die AVM2 in der Lage, die Ausführungszeit deutlich zu reduzieren, da sie häufig direkte Maschinenanweisungen erzeugen kann, um direkt ohne zeitaufwendiges Suchen von Namen auf Eigenschaften oder Aufrufmethoden zuzugreifen.
Dank des Traitsobjekts belegt ein Objekt deutlich weniger Speicherplatz als ein ähnliches Objekt in früheren Versionen von ActionScript. Ist eine Klasse versiegelt (also nicht dynamisch deklariert), benötigt eine Klasseninstanz keine Hashtabelle für dynamisch hinzugefügte Eigenschaften und enthält nur wenig mehr als einen Zeiger auf die Traitsobjekte und einige Slots für feste Eigenschaften, die in der Klasse definiert sind. Daher belegt ein Objekt, das in ActionScript 2.0 noch 100 Byte im Arbeitsspeicher belegt hat, in ActionScript 3.0 nur noch 20 Byte.
|
HINWEIS |
|
Das Traitsobjekt ist ein internes Implementationsdetail. Es besteht keine Garantie, dass es in zukünftigen Versionen von ActionScript unverändert bleibt oder nicht wieder verschwindet. |
Jedes ActionScript-Klassenobjekt verfügt über eine Eigenschaft namens prototype, die einen Verweis auf das Prototypobjekt der Klasse darstellt. Das Prototypobjekt ist ein Vermächtnis aus den Ursprüngen von ActionScript als eine prototypbasierte Sprache. Weitere Informationen finden Sie unter ActionScript 1.0.
Die prototype-Eigenschaft ist schreibgeschützt, d. h., sie kann nicht geändert werden, um auf andere Objekte zu verweisen. Dies unterscheidet sich von der prototype-Eigenschaft einer Klasse in früheren Versionen von ActionScript. Hier konnte der Prototyp neu zugewiesen werden, sodass er auf eine andere Klasse verwies. Auch wenn die Eigenschaft prototype schreibgeschützt ist, das Prototypobjekt, auf das sie verweist, ist es nicht. Anders ausgedrückt, einem Prototypobjekt können neue Eigenschaften hinzugefügt werden. Einem Prototypobjekt hinzugefügte Eigenschaften stehen allen Instanzen der Klasse zur Verfügung.
Die Prototypkette, der einzige Vererbungsmechanismus in früheren Versionen von ActionScript, spielt in ActionScript 3.0 nur noch eine untergeordnete Rolle. Der primäre Vererbungsmechanismus, die Vererbung von festen Eigenschaften, wird intern durch das Traitsobjekt abgewickelt. Eine feste Eigenschaft ist eine Variable oder eine Methode, die als Teil einer Klassendefinition definiert ist. Die Vererbung von festen Eigenschaften wird auch als Klassenvererbung bezeichnet, da sie der einzige Vererbungsmechanismus ist, der mit Schlüsselwörtern wie class, extends und override verbunden ist.
Die Vererbungskette bietet einen alternativen Vererbungsmechanismus, der dynamischer als die Vererbung fester Eigenschaften ist. Sie können dem Prototypobjekt einer Klasse Eigenschaften nicht nur als Teil der Klassendefinition hinzufügen, sondern über die Eigenschaft prototype des Klassenobjekts auch zur Laufzeit. Beachten Sie jedoch Folgendes: wenn Sie den Compiler auf den strikten Modus einstellen, können Sie nicht auf die dem Prototypobjekt hinzugefügten Eigenschaften zugreifen, es sei denn, Sie deklarieren eine Klasse mit dem Schlüsselwort dynamic.
Ein gutes Beispiel für eine Klasse, bei der mehrere Eigenschaften an das Prototypobjekt angehängt wurden, ist die Object-Klasse. Bei den Methoden toString() und valueOf() der Objektklasse handelt es sich tatsächlich um Funktionen, die den Eigenschaften des Prototypobjekts der Objektklasse zugeordnet sind. Der folgende Code zeigt, wie die Deklaration dieser Methoden theoretisch aussehen könnte (die tatsächliche Implementation unterscheidet sich aufgrund der Implementationsdetails ein wenig):
public dynamic class Object
{
prototype.toString = function()
{
// Anweisungen
};
prototype.valueOf = function()
{
// Anweisungen
};
}
Wie bereits erwähnt, können Sie eine Eigenschaft an das Prototypobjekt einer Klasse außerhalb der Klassendefinition anhängen. Beispielsweise kann die Methode toString() auch außerhalb der Objektklassendefinition definiert werden. Dies wird im folgenden Beispiel gezeigt:
Object.prototype.toString = function()
{
// Anweisungen
};
Im Gegensatz zur Vererbung von festen Eigenschaften ist für die Prototypvererbung kein Schlüsselwort override erforderlich, wenn Sie eine Methode in einer Unterklasse neu definieren möchten. Wenn Sie die Methode valueOf() in einer Unterklasse der Object-Klasse neu definieren möchten, haben Sie drei Optionen: Zunächst können Sie eine valueOf()-Methode für das Prototypobjekt der Unterklasse in der Klassendefinition definieren. Im folgenden Beispielcode wird zunächst ein Objekt namens „Foo" erstellt und dann die valueOf()-Methode des Prototypobjekts von „Foo" als Teil der Klassendefinition neu definiert. Da jede Klasse von der Object-Klasse erbt, muss das Schlüsselwort extends nicht verwendet werden.
dynamic class Foo
{
prototype.valueOf = function()
{
return "Instance of Foo";
};
}
Dann können Sie eine valueOf()-Methode für das Prototypobjekt von „Foo" außerhalb der Klassendefinition definieren. Dies wird im folgenden Beispiel gezeigt:
Foo.prototype.valueOf = function()
{
return "Instance of Foo";
};
Als dritte Möglichkeit können Sie eine feste Eigenschaft namens valueOf() als Teil der Foo-Klasse definieren. Diese Technik unterscheidet sich insofern von den anderen, als dass sie die Vererbung fester Eigenschaften mit der Prototypvererbung mischt. Jede Unterklasse von „Foo", die valueOf() neu definieren möchte, muss das Schlüsselwort override verwenden. Im folgenden Beispielcode wird gezeigt, wie valueOf() als eine feste Eigenschaft in „Foo" definiert wird:
class Foo
{
function valueOf():String
{
return "Instance of Foo";
}
}
Die beiden separaten Vererbungsmechanismen, die Vererbung fester Eigenschaften und die Prototypvererbung, stellen hinsichtlich der Eigenschaften und Methoden der Hauptklassen eine interessante Herausforderung an die Kompatibilität. Die Kompatibilität mit der ECMAScript, Edition 4 Draft-Sprachspezifikation erfordert die Verwendung der Prototypvererbung. Dies bedeutet, dass die Eigenschaften und Methoden einer Hauptklasse für das Prototypobjekt dieser Klasse definiert werden. Andererseits verlangt die Kompatibilität mit der Flash Player-API nach einer Vererbung fester Eigenschaften. Dies bedeutet, dass die Eigenschaften und Methoden einer Hauptklasse mithilfe der Schlüsselwörter const, var und function in der Klassendefinition definiert sind. Darüber hinaus kann die Verwendung der festen Eigenschaften anstelle der Prototypversionen eine deutliche Leistungsverbesserung zur Laufzeit bedeuten.
ActionScript 3.0 löst dieses Problem, indem für die Hauptklassen sowohl die Prototypvererbung als auch die Vererbung fester Eigenschaften verwendet wird. Jede Hauptklasse enthält zwei Sätze mit Eigenschaften und Methoden. Ein Satz wird zur Kompatibilität mit der ECMAScript-Spezifikation am Prototypobjekt definiert, der andere Satz wird zur Kompatibilität mit der Flash Player-API mit festen Eigenschaften und dem AS3-Namespace definiert.
Der AS3-Namespace bietet einen bequemen Mechanismus zur Auswahl zwischen den beiden Eigenschaften- und Methodensätzen. Wenn Sie den AS3-Namespace nicht verwenden, erbt eine Instanz der Hauptklasse die Eigenschaften und Methoden, die im Prototypobjekt der Hauptklasse definiert wurden. Wenn Sie den AS3-Namespace verwenden, erbt eine Instanz der Hauptklasse die AS3-Versionen, da die festen Eigenschaften gegenüber den Prototypeigenschaften immer bevorzugt werden. Anders ausgedrückt, wenn eine feste Eigenschaft verfügbar ist, sollte sie stets anstelle einer identisch benannten Prototypeigenschaft verwendet werden.
Sie können selektiv die AS3-Namespace-Version einer Eigenschaft oder Methode verwenden, indem Sie sie mit dem AS3-Namespace qualifizieren. Im folgenden Beispielcode wird die AS3-Version der Array.pop()-Methode verwendet:
var nums:Array = new Array(1, 2, 3); nums.AS3::pop(); trace(nums); // Ausgabe: 1,2
Alternativ können Sie die Direktive use namespace verwenden, um den AS3-Namespace für alle Definitionen innerhalb eines Codeblocks zu öffnen. Im folgenden Beispielcode wird die Direktive use namespace verwendet, um den AS3-Namespace für die Methoden pop() und push() zu öffnen:
use namespace AS3; var nums:Array = new Array(1, 2, 3); nums.pop(); nums.push(5); trace(nums) // Ausgabe: 1,2,5
Darüber hinaus bietet ActionScript 3.0 Compileroptionen für jeden Eigenschaftensatz, sodass Sie den AS3-Namespace auf das gesamte Programm anwenden können. Die Compileroption -as3 stellt den AS3-Namespace, die Compileroption -es die Prototypvererbungsoption dar (es steht für ECMAScript). Um den AS3-Namespace für das gesamte Programm zu öffnen, setzen Sie die Compileroption -as3 auf true und die Compileroption -es auf false. Wenn Sie die Prototypversionen verwenden möchten, setzen Sie die Compileroptionen auf die jeweils entgegengesetzten Werte. Die Compiler-Standardeinstellungen für Adobe Flex Builder 2 und Adobe Flash CS3 Professional lauten -as3 = true und -es = false.
Wenn Sie eine der Hauptklasse erweitern und Methoden überschreiben möchten, müssen Sie verstanden haben, wie der AS3-Namespace Ihr Vorgehen beim Deklarieren einer überschriebenen Methode beeinflussen kann. Wenn Sie den AS3-Namespace verwenden, muss eine Methodenüberschreibung einer Hauptklassenmethode auch den AS3-Namespace zusammen mit dem Attribut override verwenden. Wenn Sie den AS3-Namespace nicht verwenden und eine Hauptklassenmethode in einer Unterklasse neu definieren möchten, dürfen Sie den AS3-Namespace oder das Schlüsselwort override nicht verwenden.
Flash CS3
Eine E-Mail an mich senden, wenn dieser Seite Kommentare hinzugefügt werden | Kommentarbericht
Aktuelle Seite: http://livedocs.adobe.com/flash/9.0_de/main/00000069.html