Erweitern der Array-Klasse

Flash Player 9 und höher, Adobe AIR 1.0 und höher

Die Array-Klasse ist eine der wenigen Hauptklassen, die nicht endgültig festgelegt („final“) ist. Dies bedeutet, dass Sie Unterklassen der Array-Klasse erstellen können. In diesem Abschnitt wird an einem Beispiel erläutert, wie eine Unterklasse der Array-Klasse erstellt wird. Darüber hinaus werden einige Probleme erörtert, die unter Umständen auftreten können.

Wie weiter oben erwähnt, sind Arrays in ActionScript nicht typisiert, Sie können jedoch eine Array-Unterklasse erstellen, die nur Elemente eines bestimmten Datentyps enthalten kann. In dem Beispiel in den folgenden Abschnitten wird eine Array-Unterklasse mit dem Namen „TypedArray“ erstellt, bei der die Elemente auf Werte des im ersten Parameter angegebenen Datentyps beschränkt sind. Die TypedArray-Klasse wird hier lediglich exemplarisch zur Erweiterung der Array-Klasse verwendet und eignet sich möglicherweise aus mehreren Gründen nicht für die Praxis. Erstens erfolgt die Typüberprüfung zur Laufzeit und nicht bei der Kompilierung. Zweitens werden Diskrepanzen ignoriert, die in der TypedArray-Methode auftreten können, und keine Ausnahmen ausgelöst. Die Methoden können jedoch auf einfache Weise so geändert werden, dass Ausnahmen ausgelöst werden. Mit der Klasse kann drittens nicht verhindert werden, dass über den Array-Zugriffsoperator Werte jedes Datentyps in das Array eingefügt werden. Darüber hinaus wurde beim Programmierstil auf Einfachheit statt auf Leistungsoptimierung gesetzt.

Hinweis: Sie können ein Typ-Array mit den hier beschriebenen Techniken erstellen. Es empfiehlt sich jedoch, stattdessen ein Vector-Objekt zu verwenden. Eine Vector-Instanz ist ein Typ-Array in Reinform und bietet im Vergleich mit der Array-Klasse oder den Unterklassen Leistungssteigerungen und weitere Vorteile. In diesem Abschnitt soll die Erstellung einer Array-Unterklasse veranschaulicht werden.

Deklarieren der Unterklasse

Geben Sie mit dem Schlüsselwort extends an, dass es sich um eine Unterklasse der Array-Klasse handelt. Bei einer Array-Unterklasse sollte wie bei der Array-Klasse das dynamic -Attribut verwendet werden. Andernfalls kann die Unterklasse nicht ordnungsgemäß verwendet werden.

Im folgenden Code ist die Definition der TypedArray-Klasse dargestellt. Sie enthält eine Konstante für den Datentyp, eine Konstruktormethode und die vier Methoden zum Hinzufügen von Elementen zum Array. Der Code für die einzelnen Methoden ist im folgenden Codebeispiel nicht angegeben, er wird jedoch in den folgenden Abschnitten getrennt und vollständig erläutert.

public dynamic class TypedArray extends Array 
{ 
    private const dataType:Class; 
 
    public function TypedArray(...args) {} 
     
    AS3 override function concat(...args):Array {} 
     
    AS3 override function push(...args):uint {} 
     
    AS3 override function splice(...args) {} 
     
    AS3 override function unshift(...args):uint {} 
}

Bei allen vier überschriebenen Methoden wird der AS3-Namespace anstelle des public -Attributs verwendet, da in diesem Beispiel davon ausgegangen wird, dass die Compileroption -as3 auf true und die Compileroption -es auf false gesetzt ist. Dies sind die Standardeinstellungen für Adobe Flash Builder und AdobeFlashProfessional.

Erfahrene Entwickler, die die Verwendung der Prototypvererbung bevorzugen, können zwei kleine Änderungen an der TypedArray-Klasse vornehmen, sodass diese mit der auf true gesetzten Compileroption -es kompiliert werden kann. Entfernen Sie zunächst alle Vorkommen des override -Attributs und ersetzen Sie den AS3-Namespace durch das public -Attribut. Ersetzen Sie dann alle vier Vorkommen von super durch Array.prototype .

TypedArray-Konstruktor

Der Konstruktor der Unterklasse stellt eine interessante Herausforderung dar, da er eine Liste mit Argumenten beliebiger Länge annehmen muss. Die Herausforderung besteht in der Weise, auf die die Argumente an den Superkonstruktor übergeben werden, um das Array zu erstellen. Wenn Sie die Liste der Argumente als Array übergeben, wird sie im Superkonstruktor als einzelnes Argument des Array-Typs erkannt, und das resultierende Array hat immer die Länge eines Elements. Normalerweise werden übergebene Argumentlisten mithilfe der Function.apply() -Methode verarbeitet, bei der ein Array mit Argumenten als zweiter Parameter verwendet wird, das Array jedoch beim Ausführen der Funktion in eine Liste mit Argumenten konvertiert wird. Leider kann die Function.apply() -Methode bei Konstruktoren nicht verwendet werden.

Die einzige verbleibende Möglichkeit besteht darin, den Code des Array-Konstruktors im TypedArray-Konstruktor neu zu erstellen. Im folgenden Codebeispiel ist der im Konstruktor der Array-Klasse verwendete Algorithmus dargestellt, den Sie im Konstruktor der Array-Unterklasse wiederverwenden können:

public dynamic class Array 
{ 
    public function Array(...args) 
    { 
        var n:uint = args.length 
        if (n == 1 && (args[0] is Number)) 
        { 
            var dlen:Number = args[0]; 
            var ulen:uint = dlen; 
            if (ulen != dlen) 
            { 
                throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")"); 
            } 
            length = ulen; 
        } 
        else 
        { 
            length = n; 
            for (var i:int=0; i < n; i++) 
            { 
                this[i] = args[i]  
            } 
        } 
    } 
}

Für den TypedArray-Konstruktor wird im Wesentlichen der gleiche Code verwendet wie beim Array-Konstruktor, es werden nur vier Änderungen am Code vorgenommen. Die Parameterliste enthält erstens einen neuen erforderlichen Parameter des Class-Typs, mit dem der Datentyp des Arrays angegeben werden kann. Der an den Konstruktor übergebene Datentyp wird zweitens der dataType -Variablen zugewiesen. In der else -Anweisung wird drittens der Wert der length -Eigenschaft nach der for -Schleife zugewiesen, sodass length nur Argumente mit dem korrekten Datentyp enthält. Im Rumpf der for -Schleife wird viertens die überschriebene Version der push() -Methode verwendet, sodass ausschließlich Argumente mit dem korrekten Datentyp zum Array hinzugefügt werden. Im folgenden Beispiel ist die TypedArray-Konstruktorfunktion dargestellt:

public dynamic class TypedArray extends Array 
{ 
    private var dataType:Class; 
    public function TypedArray(typeParam:Class, ...args) 
    { 
        dataType = typeParam; 
        var n:uint = args.length 
        if (n == 1 && (args[0] is Number)) 
        { 
            var dlen:Number = args[0]; 
            var ulen:uint = dlen 
            if (ulen != dlen) 
            { 
                throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")") 
            } 
            length = ulen; 
        } 
        else 
        { 
            for (var i:int=0; i < n; i++) 
            { 
                // type check done in push()  
                this.push(args[i]) 
            } 
            length = this.length; 
        } 
    } 
}

Überschriebene Methoden der TypedArray-Klasse

Bei der TypedArray-Klasse werden die vier Methoden der Array-Klasse überschrieben, mit denen Elemente zu einem Array hinzugefügt werden können. Bei allen überschriebenen Methoden wird jeweils eine Typüberprüfung eingefügt, über die verhindert wird, dass Elemente mit einem ungültigen Datentyp hinzugefügt werden. Anschließend wird bei allen Methoden die Superclass-Version der jeweiligen Methode aufgerufen.

Die push() -Methode durchläuft die Liste der Argumente mit einer for..in -Schleife und führt für jedes Argument eine Typüberprüfung durch. Alle Argumente, die nicht den korrekten Datentyp aufweisen, werden mit der splice() -Methode aus dem args -Array entfernt. Nach Abschluss der for..in -Schleife enthält das args -Array nur Werte mit dem Typ dataType . Die Superclass-Version von push() wird dann mit dem aktualisierten args -Array aufgerufen, wie im folgenden Codebeispiel dargestellt:

    AS3 override function push(...args):uint 
    { 
        for (var i:* in args) 
        { 
            if (!(args[i] is dataType)) 
            { 
                args.splice(i,1); 
            } 
        } 
        return (super.push.apply(this, args)); 
    }

Mit der concat() -Methode wird das temporäre TypedArray-Array mit dem Namen passArgs erstellt, in dem die Argumente nach erfolgreicher Typüberprüfung gespeichert werden. Dadurch kann der in der push() -Methode vorhandene Code für die Typüberprüfung erneut verwendet werden. Mit einer for..in -Schleife wird das args -Array durchlaufen. Anschließend wird push() für jedes Argument aufgerufen. Da passArgs als TypedArray typisiert ist, wird die TypedArray-Version von push() ausgeführt. Mit der concat() -Methode wird dann die zugehörige Superclass-Version aufgerufen, wie im folgenden Codebeispiel dargestellt:

    AS3 override function concat(...args):Array 
    { 
        var passArgs:TypedArray = new TypedArray(dataType); 
        for (var i:* in args) 
        { 
            // type check done in push() 
            passArgs.push(args[i]); 
        } 
        return (super.concat.apply(this, passArgs)); 
    }

Bei der splice() -Methode wird eine beliebig lange Liste mit Argumenten verwendet. Die ersten beiden Argumente verweisen jedoch immer auf eine Indexposition und die Anzahl der zu löschenden Elemente. Aus diesem Grund wird mit der überschriebenen splice() -Methode nur eine Typüberprüfung der Elemente des args -Arrays ab Indexposition 2 durchgeführt. Im Codebeispiel wird in der for -Schleife scheinbar ein rekursiver Aufruf von splice() ausgeführt. Es handelt sich jedoch um keinen rekursiven Aufruf, da args den Array-Typ und nicht den TypedArray-Typ aufweist. Dies bedeutet, dass beim Aufrufen von args.splice() die Superclass-Version der Methode aufgerufen wird. Nach Abschluss der for..in -Schleife enthält das args -Array ab Indexposition 2 nur Werte mit dem korrekten Datentyp. Mit splice() wird zudem die zugehörige Superclass-Version aufgerufen, wie im folgenden Codebeispiel dargestellt:

    AS3 override function splice(...args):* 
    { 
        if (args.length > 2) 
        { 
            for (var i:int=2; i< args.length; i++) 
            { 
                if (!(args[i] is dataType)) 
                { 
                    args.splice(i,1); 
                } 
            } 
        } 
        return (super.splice.apply(this, args)); 
    }

Bei der unshift() -Methode, mit der Elemente am Anfang eines Arrays hinzugefügt werden, kann ebenfalls eine beliebige Liste mit Argumenten übergeben werden. Bei der überschriebenen unshift() -Methode wird ein ähnlicher Algorithmus wie bei der push() -Methode verwendet, wie im folgenden Codebeispiel dargestellt:

    AS3 override function unshift(...args):uint 
    { 
        for (var i:* in args)  
        { 
            if (!(args[i] is dataType)) 
            { 
                args.splice(i,1); 
            } 
        } 
        return (super.unshift.apply(this, args)); 
    } 
}