Pakete und Namespaces sind miteinander verwandte Konzepte. Mit Paketen können Sie Klassendefinitionen bündeln, um die gemeinsame Nutzung von Code zu vereinfachen und Benennungskonflikte zu minimieren. Mit Namespaces steuern Sie die Sichtbarkeit von Bezeichnern, wie z. B. Eigenschaften- und Methodennamen. Namespaces können auf Code unabhängig davon angewendet werden, ob dieser sich innerhalb oder außerhalb eines Pakets befindet. Pakete ermöglichen Ihnen das Strukturieren Ihrer Klassendateien, mit Namespaces verwalten Sie die Sichtbarkeit von einzelnen Eigenschaften und Methoden.
Pakete
In ActionScript 3.0 werden Pakete mit Namespaces implementiert, dennoch sind Pakete und Namespaces keine Synonyme. Beim Deklarieren eines Paketes erstellen Sie implizit einen Sondertyp eines Namespace, der dann bei der Kompilierung garantiert bekannt ist. Explizit erstelle Namespaces hingegen sind bei der Kompilierung nicht unbedingt bekannt.
Im folgenden Beispiel wird die Direktive
package
zum Erstellen eines einfachen Pakets verwendet, das eine Klasse enthält:
package samples
{
public class SampleCode
{
public var sampleGreeting:String;
public function sampleFunction()
{
trace(sampleGreeting + " from sampleFunction()");
}
}
}
Der Name der Klasse in diesem Beispiel lautet „SampleCode“. Da sich die Klasse im samples-Paket befindet, wandelt der Compiler den Klassennamen während der Kompilierung automatisch in dessen vollständig qualifizierten Namen (samples.SampleCode) um. Darüber hinaus wandelt der Compiler die Namen aller Eigenschaften oder Methoden um, sodass
sampleGreeting
und
sampleFunction()
zu
samples.SampleCode.sampleGreeting
und
samples.SampleCode.sampleFunction()
werden.
Viele Entwickler, insbesondere diejenigen mit Erfahrungen in der Programmierung mit Java, platzieren Klassen nur in der obersten Ebene eines Pakets. ActionScript 3.0 unterstützt in der obersten Ebene eines Pakets jedoch nicht nur Klassen, sondern auch Variablen, Funktionen und sogar Anweisungen. Eine erweiterte Einsatzmöglichkeit dieses Merkmals ist das Definieren eines Namespace auf der obersten Ebene eines Pakets, sodass er allen Klassen in diesem Paket zur Verfügung steht. Denken Sie jedoch daran, dass nur zwei Zugriffsbezeichner,
public
und
internal
, auf der obersten Ebene eines Pakets zulässig sind. Im Gegensatz zur Programmiersprache Java, bei der Sie verschachtelte Klassen als private Klassen deklarieren können, unterstützt ActionScript 3.0 weder verschachtelte noch private Klassen.
In vielerlei Hinsicht ähneln ActionScript 3.0-Pakete den Paketen in der Programmiersprache Java. Wie Sie im vorangegangenen Beispiel gesehen haben, werden vollständig qualifizierte Paketverweise ebenso wie in Java mit dem Punktoperator (
.
) ausgedrückt. Mit Paketen können Sie Ihren Code intuitiv und hierarchisch anordnen, sodass er auch von anderen Programmierern verwendet werden kann. Dies vereinfacht die gemeinsame Nutzung von Code, indem von Ihnen erstellte Pakete von anderen Programmierern verwendet und Sie von anderen Programmierern erstellte Pakete in Ihren Code integrieren können.
Darüber hinaus können Sie mit Paketen sicherstellen, dass von Ihnen verwendete Bezeichnernamen einmalig sind und somit nicht zu Konflikten mit anderen Bezeichnernamen führen. Viele sagen sogar, dass dies der wichtigste Vorteil von Paketen ist. Angenommen, zwei Programmierer möchten ihren Code gemeinsam verwenden. Jeder hat eine Klasse mit der Bezeichnung „SampleCode“ erstellt. Ohne Pakete würde dies zu einem Namenskonflikt führen. Die einzige Lösung wäre, eine der beiden Klassen umzubenennen. Mit Paketen lässt sich der Namenskonflikt einfach vermeiden, indem eine Klasse (oder am besten beide Klassen) in Paketen mit einmaligen Namen platziert werden.
Sie können auch eingebettete Punkte in Ihren Paketnamen aufnehmen, um verschachtelte Pakete zu erstellen. Auf diese Weise können Sie eine hierarchische Paketstruktur anlegen. Ein gutes Beispiel hierfür ist das von ActionScript 3.0 bereitgestellte flash.display-Paket, das im flash-Paket verschachtelt ist.
Der Großteil von ActionScript 3.0 ist unter dem flash-Paket organisiert. Beispielsweise enthält das flash.display-Paket die API für die Anzeigeliste und das flash.events-Paket das neue Ereignismodell.
Erstellen von Paketen
ActionScript 3.0 bietet Ihnen eine enorme Flexibilität bei der Strukturierung Ihrer Pakete, Klassen und Quelldateien. Frühere ActionScript-Versionen gestatteten nur eine Klasse pro Quelldatei und verlangten, dass der Name der Quelldatei dem Namen der Klasse entsprach. Mit ActionScript 3.0 können Sie mehrere Klassen in eine Quelldatei aufnehmen, doch für Code außerhalb der Datei ist pro Datei nur eine Klasse verfügbar. Anders ausgedrückt, in einer Paketdeklaration kann in jeder Datei nur eine Klasse deklariert werden. Sie müssen alle zusätzlichen Klassen außerhalb Ihrer Paketdefinition deklarieren. Auf diese Weise werden diese Klassen auch für Code sichtbar, der sich außerhalb dieser Quelldatei befindet. Der Name der innerhalb einer Paketdefinition deklarierten Klasse muss dem Namen der Quelldatei entsprechen.
Darüber hinaus bietet ActionScript 3.0 mehr Flexibilität bei der Deklaration von Paketen. In früheren Versionen von ActionScript waren Pakete lediglich Verzeichnisse, in denen Sie Quelldateien platzierten. Sie haben keine Pakete mit der
package
-Anweisung deklariert, sondern stattdessen den Paketnamen als Teil des vollständig qualifizierten Klassennamens in Ihre Klassendeklaration aufgenommen. Obwohl Pakete in ActionScript 3.0 noch immer Verzeichnisse darstellen, können sie mehr als nur Klassen enthalten. In ActionScript 3.0 deklarieren Sie ein Paket mit der Anweisung
package
, d. h. Sie können auch Variable, Funktionen und Namespaces auf oberster Ebene eines Pakets deklarieren. Es ist sogar möglich, ausführbare Anweisungen in die oberste Ebene eines Pakets aufzunehmen. Wenn Sie Variablen, Funktionen oder Namespaces auf der obersten Ebene eines Pakets deklarieren, stehen Ihnen nur die Attribute
public
und
internal
zur Verfügung. Darüber hinaus kann nur eine Deklaration auf Paketebene pro Datei das Attribut
public
verwenden, unabhängig davon, ob eine Klasse, Variable, Funktion oder ein Namespace deklariert wird.
Pakete eignen sich insbesondere zum Strukturieren Ihres Codes und zum Vermeiden von Namenskonflikten. Verwechseln Sie das Konzept der Pakete jedoch nicht mit dem Konzept der Klassenvererbung. Zwei Klassen im selben Paket haben den gleichen Namespace, müssen aber nicht unbedingt miteinander verwandt sein. Entsprechend hat ein verschachteltes Paket möglicherweise keine semantische Beziehung zu seinem übergeordneten Paket.
Importieren von Paketen
Wenn Sie eine Klasse in einem Paket verwenden möchten, müssen Sie entweder das Paket oder die gewünschte Klasse importieren. Diese Vorgehensweise unterscheidet sich von der in ActionScript 2.0; hier war das Importieren von Klassen optional.
Dies kann anhand des bereits genannten Beispiels der SampleCode-Klasse verdeutlicht werden. Wenn sich die Klasse in einem Paket namens „samples“ befindet, müssen Sie die Klasse mit einer der folgenden Anweisungen importieren, bevor Sie sie verwenden können:
import samples.*;
oder
import samples.SampleCode;
Im Allgemeinen müssen
import
-Anweisungen so genau wie möglich angegeben werden. Wenn Sie nur die SampleCode-Klasse aus dem samples-Paket verwenden möchten, so importieren Sie anstelle des gesamten Pakets nur die SampleCode-Klasse. Das Importieren gesamter Pakete kann zu unerwarteten Namenskonflikten führen.
Der Quellcode, der das Paket oder die Klasse definiert, muss in Ihrem
Klassenpfad
platziert werden. Der Klassenpfad ist eine benutzerdefinierte Liste der lokalen Verzeichnispfade, die festlegt, wo der Compiler nach importierten Paketen und Klassen sucht. Manchmal wird der Klassenpfad auch als
Erstellungspfad
oder
Quellpfad
bezeichnet.
Nachdem die Klasse oder das Paket korrekt importiert wurde, können Sie entweder den vollständig qualifizierten Namen der Klasse (samples.SampleCode) oder einfach nur den Klassennamen selbst (SampleCode) verwenden.
Vollständig qualifizierte Namen eignen sich insbesondere dann, wenn identisch benannte Klassen, Methoden oder Eigenschaften zu mehrdeutigem Code führen, sind aber schwierig zu verwalten, wenn sie für alle Bezeichner verwendet werden. Wenn Sie z. B. eine SampleCode-Klasseninstanz instanziieren, wird der Code durch die Verwendung von vollständig qualifizierten Namen sehr lang:
var mySample:samples.SampleCode = new samples.SampleCode();
Je größer die Anzahl der Ebenen in den verschachtelten Paketen ist, desto schlechter ist die Lesbarkeit des Codes. Wenn Sie sicher sind, dass mehrdeutige Bezeichner kein Problem darstellen, können Sie die Lesbarkeit Ihres Codes verbessern, indem Sie einfache Bezeichner verwenden. Beispielsweise wird das Instanziieren einer neuen Instanz der SampleCode-Klasse weit weniger ausführlich, wenn Sie nur den Klassenbezeichner verwenden:
var mySample:SampleCode = new SampleCode();
Wenn Sie hingegen versuchen, die Bezeichnernamen zu verwenden, ohne zunächst das entsprechende Paket bzw. die entsprechende Klasse zu importieren, kann der Compiler die Klassendefinitionen nicht finden. Wenn Sie andererseits ein Paket oder eine Klasse importieren, führt jeder Versuch, einen Namen zu definieren, der mit einem importierten Namen in Konflikt steht, zu einer Fehlermeldung.
Nach dem Erstellen eines Pakets lautet der standardmäßige Zugriffsbezeichner für alle Mitglieder dieses Pakets
internal
. Dies wiederum bedeutet, dass alle Paketmitglieder standardmäßig nur für andere Mitglieder des Pakets sichtbar sind. Soll eine Klasse auch für Code außerhalb des Pakets zugänglich sein, müssen Sie die Klasse als
public
(öffentlich) deklarieren. Das folgende Paket enthält beispielsweise zwei Klassen, SampleCode und CodeFormatter:
// SampleCode.as file
package samples
{
public class SampleCode {}
}
// CodeFormatter.as file
package samples
{
class CodeFormatter {}
}
Die SampleCode-Klasse ist auch außerhalb des Pakets sichtbar, da sie als
public
deklariert wurde. Die CodeFormatter-Klasse ist jedoch nur innerhalb des samples-Pakets selbst sichtbar. Wenn Sie versuchen, außerhalb des samples-Pakets auf die CodeFormatter-Klasse zuzugreifen, wird eine Fehlermeldung erzeugt. Dies wird im folgenden Beispiel gezeigt:
import samples.SampleCode;
import samples.CodeFormatter;
var mySample:SampleCode = new SampleCode(); // okay, public class
var myFormatter:CodeFormatter = new CodeFormatter(); // error
Sollen beide Klassen auch für Code außerhalb des Pakets zugänglich sein, müssen Sie beide Klassen als
public
deklarieren. Sie können das Attribut
public
jedoch nicht auf die Paketdeklaration anwenden.
Vollständig qualifizierte Namen eignen sich zum Auflösen von Namenskonflikten, die bei der Verwendung von Paketen auftreten können. Ein solcher Fall kann entstehen, wenn Sie zwei Pakete importieren, in denen Klassen mit dem gleichen Bezeichner definiert sind. Das folgende Paket enthält beispielsweise eine Klasse mit der Bezeichnung „SampleCode“:
package langref.samples
{
public class SampleCode {}
}
Wenn Sie beide Klassen importieren, entsteht bei Verwendung der SampleCode-Klasse ein Namenskonflikt. Dies wird im folgenden Beispiel gezeigt:
import samples.SampleCode;
import langref.samples.SampleCode;
var mySample:SampleCode = new SampleCode(); // name conflict
Der Compiler weiß nicht, welche SampleCode-Klasse verwendet werden soll. Um diesen Konflikt aufzulösen, müssen Sie den vollständig qualifizierten Namen jeder Klasse angeben:
var sample1:samples.SampleCode = new samples.SampleCode();
var sample2:langref.samples.SampleCode = new langref.samples.SampleCode();
Hinweis:
Programmierer mit Erfahrungen in C++ verwechseln häufig die
import
-Anweisung mit
#include
. Die
#include
-Direktive ist in C++ unbedingt erforderlich, da C++-Compiler nur jeweils eine Datei verarbeiten und nicht in anderen Dateien nach Klassendefinitionen suchen, es sei denn, es ist explizit eine Headerdatei enthalten. ActionScript 3.0 enthält eine
include
-Direktive, aber sie ist nicht zum Importieren von Klassen und Paketen vorgesehen. Zum Importieren von Klassen und Paketen in ActionScript 3.0 verwenden Sie die
import
-Anweisung und legen die Quelldatei mit dem Paket im Klassenpfad ab.
Namespaces
Mit Namespaces haben Sie die Kontrolle über die Sichtbarkeit der von Ihnen erstellten Eigenschaften und Methoden. Stellen Sie sich die Zugriffskontrollbezeichner
public
,
private
,
protected
und
internal
als integrierte Namespaces vor. Wenn diese vordefinierten Zugriffskontrollbezeichner für Ihre Zwecke nicht ausreichen, können Sie eigene Namespaces erstellen.
Wenn Sie mit XML-Namespaces Erfahrung haben, wird Ihnen vieles vertraut vorkommen, obwohl Syntax und Details der ActionScript-Implementierung leicht von denen für XML abweichen. Auch wenn Sie noch nie mit Namespaces gearbeitet haben, können Sie unbesorgt sein – das Konzept ist einfach, doch die Implementierung verwendet einige spezielle Begriffe, die Sie lernen müssen.
Um das Konzept der Namespaces zu verstehen, müssen Sie zunächst einmal wissen, das der Name einer Eigenschaft oder Methode immer zwei Teile enthält: einen Bezeichner und einen Namespace. Der Bezeichner ist das, was Sie sich im Allgemeinen unter dem Namen vorstellen. Beispielsweise lauten die Bezeichner in der folgenden Klassendefinition
sampleGreeting
und
sampleFunction()
:
class SampleCode
{
var sampleGreeting:String;
function sampleFunction () {
trace(sampleGreeting + " from sampleFunction()");
}
}
Wenn Definitionen kein Namespace-Attribut vorangestellt ist, sind die entsprechenden Namen immer durch den Standardnamespace
internal
qualifiziert. Das bedeutet, sie sind nur für aufrufende Objekte im gleichen Paket sichtbar. Ist der Compiler auf den strikten Modus gesetzt, gibt er eine Warnung aus, dass der Namespace
internal
für alle Bezeichner ohne Namespace-Attribut gilt. Um sicherzustellen, dass ein Bezeichner überall zur Verfügung steht, müssen Sie dem Bezeichnernamen explizit das Attribut
public
voranstellen. Im vorangegangenen Beispielcode haben sowohl
sampleGreeting
als auch
sampleFunction()
den Namespace-Wert
internal
.
Bei der Verwendung von Namespaces sind drei grundlegende Schritte zu beachten: Zunächst definieren Sie den Namespace mit dem Schlüsselwort
namespace
. Beispielsweise definiert der folgende Code den Namespace
version1
:
namespace version1;
Dann wenden Sie den Namespace an, indem Sie ihn anstelle eines Zugriffskontrollbezeichners in einer Eigenschafts- oder Methodendeklaration verwenden. Das folgende Beispiel fügt eine Funktion namens
myFunction()
im Namespace
version1
ein:
version1 function myFunction() {}
Nachdem Sie den Namespace angewendet haben, können Sie im dritten Schritt mit der Direktive
use
oder durch Qualifizieren des Bezeichnernamens mit einem Namespace auf den angewendeten Namespace verweisen. Das folgende Beispiel verweist über die
use
-Direktive auf die
myFunction()
-Funktion:
use namespace version1;
myFunction();
Sie können auch einen qualifizierten Namen verwenden, um auf die
myFunction()
-Funktion zu verweisen. Dies ist im folgenden Beispiel dargestellt:
version1::myFunction();
Definieren von Namespaces
Namespaces enthalten einen Wert, den Uniform Resource Identifier (URI), der manchmal auch als
Namespace-Name
bezeichnet wird. Mit einem URI können Sie sicherstellen, dass Ihre Namespace-Definition einmalig ist.
Ein Namespace wird durch das Deklarieren einer Namespace-Definition erstellt. Dabei stehen Ihnen zwei Verfahren zur Verfügung: Entweder definieren Sie einen Namespace mit einem expliziten URI, als ob Sie einen XML-Namespace definieren würden, oder Sie lassen den URI weg. Das folgende Beispiel zeigt, wie ein Namespace mit einem URI definiert wird:
namespace flash_proxy = "http://www.adobe.com/flash/proxy";
Der URI dient als eindeutiger Identifikationsstring für diesen Namespace. Wenn Sie den URI weglassen, erstellt der Compiler einen eindeutigen internen Identifikationsstring anstelle des URI, wie im folgenden Beispiel dargestellt. Sie können nicht auf diesen internen Identifikationsstring zugreifen.
namespace flash_proxy;
Nach der Definition eines Namespace – ob mit oder ohne URI – kann dieser Namespace im gleichen Gültigkeitsbereich nicht mehr neu definiert werden. Der Versuch, einen Namespace zu definieren, obwohl schon ein Namespace im gleichen Gültigkeitsbereich existiert, führt zu einem Compiler-Fehler.
Ein in einem Paket oder einer Klasse definierter Namespace ist für Code außerhalb des Pakets oder der Klasse nicht sichtbar, es sei denn, es wird der entsprechende Zugriffskontrollbezeichner verwendet. Beispielsweise wurde der Namespace
flash_proxy
im folgenden Code im flash.utils-Paket definiert. Im folgenden Code bedeutet das Fehlen eines Zugriffskontrollbezeichners, dass der Namespace
flash_proxy
nur für Code innerhalb des flash.utils-Paket und nicht für Code außerhalb des Pakets sichtbar ist:
package flash.utils
{
namespace flash_proxy;
}
Im folgenden Code wird das
public
-Attribut verwendet, um den
flash_proxy
-Namespace auch für Code außerhalb des Pakets sichtbar zu machen:
package flash.utils
{
public namespace flash_proxy;
}
Anwenden von Namespaces
Unter Anwenden eines Namespace ist das Platzieren einer Definition in einem Namespace zu verstehen. In Namespaces können Funktionen, Variablen und Konstanten platziert werden (das Platzieren einer Klasse in einem benutzerdefinierten Namespace ist nicht möglich).
Betrachten Sie das Beispiel einer Funktion, die mit dem Zugriffskontroll-Namespace
public
deklariert wurde. Mit dem
public
-Attribut in einer Funktionsdefinition wird die Funktion in einem öffentlichen (public) Namespace platziert, wodurch die Funktion für jeden Code verfügbar ist. Ein definierter Namespace kann auf die gleiche Weise wie das
public
-Attribut verwendet werden, und die Definition ist für Code verfügbar, der auf Ihren benutzerdefinierten Namespace verweisen kann. Angenommen Sie haben einen Namespace
example1
definiert, so können Sie eine Methode mit der Bezeichnung
myFunction()
mit dem Attribut
example1
hinzufügen. Dies wird im folgenden Beispiel gezeigt:
namespace example1;
class someClass
{
example1 myFunction() {}
}
Das Deklarieren der
myFunction()
-Methode mit dem Namespace
example1
als Attribut bedeutet, dass die Methode zum Namespace
example1
gehört.
Beim Anwenden von Namespaces müssen Sie Folgendes berücksichtigen:
-
Sie können in jeder Deklaration nur einen Namespace anwenden.
-
Es gibt keine Möglichkeit, ein Namespace-Attribut auf mehrere Definitionen gleichzeitig anzuwenden. Mit anderen Worten, wenn Sie Ihren Namespace auf zehn verschiedene Funktionen anwenden möchten, müssen Sie Ihren Namespace jeder dieser zehn Funktionsdefinitionen hinzufügen.
-
Beim Anwenden eines Namespace können Sie keinen Zugriffskontrollbezeichner angeben, da sich Namespaces und Zugriffskontrollbezeichner gegenseitig ausschließen. Sie können also eine Funktion oder Eigenschaft zusätzlich zum Anwenden Ihres Namespace nicht als
public
,
private
,
protected
oder
internal
deklarieren.
Referenzieren von Namespaces
Wenn Sie eine Methode oder Eigenschaft verwenden, die mit einem der Zugriffskontroll-Namespaces wie
public
,
private
,
protected
und
internal
deklariert wurde, ist kein expliziter Verweis auf einen Namespace mehr erforderlich. Dies liegt daran, dass der Zugriff auf diese speziellen Namespaces über den Kontext gesteuert wird. Im Namespace
private
platzierte Definitionen stehen beispielsweise automatisch für Code in der gleichen Klasse zur Verfügung. Für benutzerdefinierte Namespaces existiert eine solche Kontextempfindlichkeit jedoch nicht. Um eine von Ihnen in einem benutzerdefinierten Namespace platzierte Methode oder Eigenschaft zu verwenden, müssen Sie den Namespace referenzieren.
Verweise auf Namespaces erstellen Sie mit der Direktive
use namespace
, oder Sie qualifizieren den Namen mit dem Namensqualifizierter (
::
). Das Referenzieren eines Namespace mit der Direktive
use namespace
„öffnet“ den Namespace, sodass er auf alle nicht qualifizierten Bezeichner angewendet werden kann. Angenommen Sie haben den Namespace
example1
definiert, so können Sie mithilfe von
use namespace example1
auf Namen in diesem Namespace zugreifen:
use namespace example1;
myFunction();
Sie können mehrere Namespaces gleichzeitig öffnen. Nachdem Sie einen Namespace mit
use namespace
geöffnet haben, bleibt er über den gesamten Codeblock, in dem er geöffnet wurde, offen. Es gibt keine Möglichkeit, einen Namespace explizit zu schließen.
Wenn mehrere Namespaces geöffnet sind, erhöht sich jedoch die Wahrscheinlichkeit von Namenskonflikten. Wenn Sie einen Namespace nicht öffnen möchten, können Sie die Direktive
use namespace
vermeiden, indem Sie den Methoden- oder Eigenschaftennamen mit dem Namespace und dem Namensqualifizierer qualifizieren. Das folgende Beispiel zeigt, wie der Name
myFunction()
mit dem Namespace
example1
qualifiziert wird:
example1::myFunction();
Verwenden von Namespaces
In der flash.utils.Proxy-Klasse, die einen Teil von ActionScript 3.0 bildet, finden Sie ein realistisches Beispiel eines Namespace, durch dessen Verwendung Namenskonflikte verhindert werden. Die Proxy-Klasse, ein Ersatz für die
Object.__resolve
-Eigenschaft aus ActionScript 2.0, ermöglicht Ihnen das Abfangen von Verweisen auf nicht definierte Eigenschaften oder Methoden, bevor ein Fehler auftritt. Alle Methoden der Proxy-Klasse befinden sich im
flash_proxy
-Namespace, um Namenskonflikte zu verhindern.
Um die Einsatzmöglichkeiten des
flash_proxy
-Namespace besser zu verstehen, müssen Sie wissen, wie die Proxy-Klasse verwendet wird. Die Funktionsmerkmale der Proxy-Klasse stehen nur den Klassen zur Verfügung, die von der Proxy-Klasse erben. Anders ausgedrückt, wenn Sie die Methoden der Proxy-Klasse an einem Objekt anwenden möchten, muss die Klassendefinition des Objekts auf die Proxy-Klasse ausgeweitet werden. Wenn Sie beispielsweise Versuche zum Aufrufen einer nicht definierten Methode abfangen möchten, so müssen Sie die Proxy-Klasse ausweiten und dann die
callProperty()
-Methode der Proxy-Klasse außer Kraft setzen.
Sie werden sich erinnern, dass das Implementieren von Namespaces im Allgemeinen ein dreistufiger Prozess ist, der sich aus dem Definieren, Anwenden und Referenzieren eines Namespace zusammensetzt. Da Sie jedoch keine der Methoden der Proxy-Klasse explizit aufrufen, wird der
flash_proxy
-Namespace nur definiert und angewendet, aber nicht referenziert. ActionScript 3.0 definiert den
flash_proxy
-Namespace und wendet ihn in der Proxy-Klasse an. Ihr Code muss den
flash_proxy
-Namespace nur auf die Klassen anwenden, welche die Proxy-Klasse erweitern.
Der
flash_proxy
-Namespace ist etwa wie folgt in dem flash.utils-Paket definiert:
package flash.utils
{
public namespace flash_proxy;
}
Der Namespace wird auf die Methoden der Proxy-Klasse angewendet, wie im folgenden Codeausschnitt der Proxy-Klasse dargestellt ist:
public class Proxy
{
flash_proxy function callProperty(name:*, ... rest):*
flash_proxy function deleteProperty(name:*):Boolean
...
}
Wie der folgende Code veranschaulicht, müssen Sie zunächst sowohl die Proxy-Klasse als auch den
flash_proxy
-Namespace importieren. Dann deklarieren Sie Ihre Klasse so, dass sie die Proxy-Klasse erweitert (außerdem müssen Sie das Attribut
dynamic
hinzufügen, wenn Sie im strikten Modus kompilieren). Falls Sie die
callProperty()
-Methode außer Kraft setzen, müssen Sie den
flash_proxy
-Namespace verwenden.
package
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
dynamic class MyProxy extends Proxy
{
flash_proxy override function callProperty(name:*, ...rest):*
{
trace("method call intercepted: " + name);
}
}
}
Wenn Sie eine Instanz der MyProxy-Klasse erstellen und eine nicht definierte Methode, wie z. B. die
testing()
-Methode, aufrufen (siehe folgendes Beispiel), fängt das Proxy-Objekt den Methodenaufruf ab und führt die Anweisungen in der überschriebenen
callProperty()
-Methode aus (in diesem Fall eine einfache
trace()
-Anweisung).
var mySample:MyProxy = new MyProxy();
mySample.testing(); // method call intercepted: testing
Die Aufnahme der Methoden der Proxy-Klasse in den
flash_proxy
-Namespace hat zwei Vorteile. Zunächst wird durch einen separaten Namespace die öffentliche Schnittstelle jeder Klasse übersichtlicher, welche die Proxy-Klasse erweitert. (Es gibt etwa ein Dutzend Methoden in der Proxy-Klasse, die Sie außer Kraft setzen können. Keine dieser Methoden wird direkt aufgerufen. Das Platzieren aller dieser Methoden im öffentlichen Namespace könnte verwirrend wirken.) Darüber hinaus werden durch Verwenden des
flash_proxy
-Namespace Namenskonflikte vermieden, falls Ihre Proxy-Unterklasse Instanzenmethoden mit Namen enthält, die Methoden in der Proxy-Klasse gleichen. Angenommen Sie möchten eine Ihrer eigenen Methoden
callProperty()
nennen. Der folgende Code wird akzeptiert, da sich Ihre Version der
callProperty()
-Methode in einem anderen Namespace befindet:
dynamic class MyProxy extends Proxy
{
public function callProperty() {}
flash_proxy override function callProperty(name:*, ...rest):*
{
trace("method call intercepted: " + name);
}
}
Mit Namespaces kann auch ein Zugriff auf Methoden oder Eigenschaften bereitgestellt werden, der nicht über die vier Zugriffskontrollbezeichner (
public
,
private
,
internal
und
protected
) möglich ist. Vielleicht haben Sie einige Dienstprogrammmethoden, die über mehrere Pakete verteilt sind. Diese Methoden sollen für alle Pakete zur Verfügung stehen, Sie möchten sie aber nicht als öffentliche Methoden deklarieren. In diesem Fall erstellen Sie einen Namespace und verwenden ihn als Ihren eigenen speziellen Zugriffskontrollbezeichner.
Im folgenden Beispiel werden zwei Funktionen aus unterschiedlichen Paketen in einem benutzerdefinierten Namespace zusammengeführt. Durch Gruppieren dieser Funktionen im gleichen Namespace können Sie beide Funktionen mit nur einer
use namespace
-Anweisung für eine Klasse oder ein Paket sichtbar machen.
Dieses Beispiel verwendet vier Dateien, um diese Technik zu veranschaulichen. Alle Dateien müssen sich in Ihrem Klassenpfad befinden. Die erste Datei, „myInternal.as“, dient zum Definieren des
myInternal
-Namespace. Da sich diese Datei in einem Paket namens „example“ befindet, müssen Sie die Datei in einem Ordner mit der Bezeichnung „example“ speichern. Der Namespace wird als
public
markiert, sodass er in andere Pakete importiert werden kann.
// myInternal.as in folder example
package example
{
public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples";
}
Mit der zweiten Datei, „Utility.as“, und der dritten Datei, „Helper.as“, werden die Klassen mit den Methoden definiert, die anderen Paketen zur Verfügung stehen sollen. Die Utility-Klasse befindet sich im Paket „example.alpha“. Dies bedeutet, dass die Datei in einem Ordner namens „alpha“ gespeichert werden muss, der wiederum ein Unterordner von „example“ ist. Die Helper-Klasse befindet sich im Paket „example.beta“. Dies bedeutet, dass die Datei in einem Ordner namens „beta“ gespeichert werden muss, der wiederum ein Unterordner von „example“ ist. Beide Pakete, „example.alpha“ und „example.beta“, müssen den Namespace importieren, bevor sie ihn verwenden können.
// Utility.as in the example/alpha folder
package example.alpha
{
import example.myInternal;
public class Utility
{
private static var _taskCounter:int = 0;
public static function someTask()
{
_taskCounter++;
}
myInternal static function get taskCounter():int
{
return _taskCounter;
}
}
}
// Helper.as in the example/beta folder
package example.beta
{
import example.myInternal;
public class Helper
{
private static var _timeStamp:Date;
public static function someTask()
{
_timeStamp = new Date();
}
myInternal static function get lastCalled():Date
{
return _timeStamp;
}
}
}
Die vierte Datei, „NamespaceUseCase.as“, ist die Hauptanwendungsklasse. Sie muss sich in einem Ordner auf gleicher Ebene wie „example“ befinden. In Flash Professional würde diese Klasse als Dokumentklasse für die FLA-Datei verwendet werden. Die NamespaceUseCase-Klasse importiert auch den
myInternal
-Namespace und verwendet ihn zum Aufrufen der beiden statischen Methoden, die sich in den anderen Paketen befinden. In diesem Beispiel werden statische Methoden nur zur Vereinfachung des Codes verwendet. Im Namespace
myInternal
können sowohl statische als auch Instanzmethoden platziert werden.
// NamespaceUseCase.as
package
{
import flash.display.MovieClip;
import example.myInternal; // import namespace
import example.alpha.Utility;// import Utility class
import example.beta.Helper;// import Helper class
public class NamespaceUseCase extends MovieClip
{
public function NamespaceUseCase()
{
use namespace myInternal;
Utility.someTask();
Utility.someTask();
trace(Utility.taskCounter); // 2
Helper.someTask();
trace(Helper.lastCalled); // [time someTask() was last called]
}
}
}
|
|
|