2010-04-10 5 views
5

Ich habe ein System geschrieben, die zur Laufzeit einige Vorlagen erzeugt und erzeugt dann einige auf diesen Vorlagen basieren Objekte. Ich hatte die Idee, dass die Vorlagen Erweiterungen der Klasse Klasse sein könnten, aber das führte zu einigen großartigen Fehler:Ist es legal, die Class-Klasse zu erweitern?

VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds. 

Was ich frage mich, wenn Subklassifizieren Klasse auch möglich ist, wenn es vielleicht etwas Fall ist, wo Dies wäre angemessen und nicht nur ein grober Missbrauch von OOP. Ich glaube, das sollte möglich sein, da Sie mit ActionScript Variablen vom Typ Class erstellen können. Diese Verwendung ist in den LiveDocs entry for Class beschrieben, aber ich habe nicht erwähnt von Subklassen Klasse gesehen.

Hier ist ein Pseudo-Code Beispiel:

class Foo extends Class 

var A:Foo = new Foo(); // A is a class 
trace(A is Class); // true, right? 
var b = new A(); // b is an instance of class A 

Ich habe keine Ahnung, was die Art der b wäre. Wäre es das?

trace(b is A); // true? 

Aber dann könnte man die Variable b Typ A, wie in var b:A = new A();, obwohl A eingeben existiert nicht erst zur Laufzeit? Ich habe gelesen, dass dies nicht möglich ist, wie A nicht statisch auflösbar ist, aber ich meine eigenen Tests mache diese Möglichkeit zu erkunden.

Letztendlich ist der Zweck, neue Klassen zur Laufzeit zu generieren und dann Instanzen dieser Klassen zu erstellen.

Zusammengefasst: Sie können die Klasse Klasse Unterklasse? Wenn ja, wie können Sie es ohne Fehler machen und welcher Typ sind die Instanzen der Klassenunterklasse?

+0

Die Hauptfrage ist: Ist Klasse eine Klasse? –

+0

Nun, ich frage tatsächlich, ob Sie die Class-Klasse unterklassieren können, oder ob das ein Missbrauch des Klassenmodells ist. Ich weiß bereits, dass Klasse eine Klasse ist; Hier ist die Klasse class livedoc: http://help.adobe.com/de_DE/AS3LCR/Flash_10.0/Class.html – ivanreese

+0

ein instanceof b // true –

Antwort

1

Hier sind die Ergebnisse meiner eigenen Forschung im Detail:

Erweiterung der Klasse Klasse an sich unmöglich zu sein scheint, obwohl dies nirgends dokumentiert ist nicht gut, dass ich noch nicht gesehen habe.Aus meiner Untersuchung bin ich nun davon überzeugt, dass die Klasse Klasse selbst nicht alle Qualitäten enthält, die die anderen Top Level-Klassen haben, obwohl sie alle von der Klasse Object ausgehen.

Noch frustrierender ist die Tatsache, dass das Unterklassifizieren verschiedener Top Level-Klassen zu mehreren unterschiedlichen Fehlermeldungen führt, was es etwas schwierig macht zu sagen, welche Probleme auftreten. Um mit einem einfachen Beispiel zu beginnen, wenn Sie viele von Actionscript primitive Datentypen (int, uint, Zahl, String, Boolean usw.), Unterklasse versuchen, erhalten Sie die folgenden Compiler Fehler:

1016: Base class is final. 

Dies macht Sinn , weil bei der Dokumentation für jede dieser Klassen suchen zeigt, dass sie in der Tat sind endgültig:

Package  Top Level 
Class   public final class Boolean 
Inheritance Boolean -> Object 

Das letzte Stichwort, bedeutet natürlich, dass eine andere Klasse, die Klasse nicht erweitern kann als letzte markiert. Betrachten wir nun für ein komplizierteres Beispiel eine Erweiterung der Function-Klasse. Die Funktionsklasse ist gemäß den Dokumenten nicht endgültig. Da es nicht endgültig ist, bedeutet das, dass wir die Function-Klasse erweitern können, um eigene spezialisierte Funktionsobjekte zu erstellen? Hier ist eine Definition:

class MyFunction extends Function { /*...*/ } 

.. und dann bei Laufzeit:

VerifyError: Error #1103: Class ::MyFunction cannot extend final base class. 

dies vergleichen mit dem primitiven Datentyp Fehler oben. Dieser Fehler trat zur Kompilierungszeit auf, da die geerbte primitive Klasse tatsächlich als final markiert wurde. Die Funktionsklasse ist nicht markiert endgültig aber die Klasse verhält sich noch, als ob es war, nur zur Laufzeit.

Jetzt kommen wir zum Hauptproblem der Frage: Erweiterung der Klasse Klasse. Wie bei der Function-Klasse ist die Class-Klasse nicht final. Außerdem ist die Class-Klasse dynamisch, was bedeutet, dass neue Eigenschaften zu einem Klassenobjekt zur Laufzeit hinzugefügt werden können.

Als eine interessante Randbemerkung: Die Function-Klasse ist auch dynamisch, und ich glaube, dass dieser Teil von was die fortgesetzte Unterstützung der alten prototypischen Vererbungsmechanismen im ECMAscript-Dialekt ermöglicht. In diesem Dialekt werden Funktionen als Klassen einer Art (also als Prototypen) verwendet, und die Fähigkeit von Funktionen, Eigenschaften zur Laufzeit hinzuzufügen, ist Teil der Macht der prototypischen Vererbung.

Jetzt verstehe ich, dass Eigenschaften eines Klassenobjekts die gleichen sind wie statische Eigenschaften, die für jede Instanz dieser Klasse verfügbar sind. Daher sollte es logisch sinnvoll sein, dass jemand ein Klassenobjekt zur Laufzeit manipulieren möchte, um es ihnen zu ermöglichen, das Verhalten dieser Klasse und ihrer Instanzen zu ändern. Dass die Klasse Klasse dynamisch ist, verstärkt diese Vorstellung.

Da die Class-Klasse nicht endgültig ist, war ich gespannt, ob man die Class-Klasse erweitern, ihre eigene Spezialisierung des Class-Modells erstellen und irgendwo in der Meta-Language-Domain arbeiten kann. Ich werde für einen weiteren Tag die Diskussion darüber, warum jemand dies tun möchte, und welche Macht es hypothetisch erlauben würde, verlassen. Als abschließendes Beispiel wollen wir nun die Class-Klasse erweitern. Hier ist eine Definition:

// the definition causes no errors on its own, even though the compiler "sees" it 
class MyClass extends Class { /*...*/ } 

/* elsewhere */ 

MyClass; // the only mention of MyClass beyond the definition 

..und dann bei Laufzeit:

verify global$init() 
        stack: 
        scope: 
        locals: global 

/* snip about 120 lines */ 

    46:getlex 34 
        stack: global Class$? 
        scope: global Object$ Class$ 
        locals: global 
    48:newclass MyClass$cinit() 
VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds. 

    at global$init() 

Heiligen stacktrace! Die VerifyError ist für fehlerhafte SWF-Daten reserviert. Basierend auf dem, was ich finden konnte, neigt ein "Bug" im Flash Player dazu, sich zu manifestieren. In jedem Fall liegt dies etwas über einem normalen ActionScript-Fehler.

An diesem Punkt wird es ziemlich schwierig, genau zu verstehen, was passiert, aber das ist, was ich bisher ableiten konnte.

VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds. 

I (fälschlicherweise, siehe unten Kommentar) glauben, dass „ABC“ steht für abstrakte Basisklasse, die ein Begriff Klassen angewandt wird, die nicht instanziiert werden kann, nur erweitert. Der obige erschreckende Fehler kommt jedoch nicht an einem Punkt der Instanziierung, sondern beim ersten Zugriff der Unterklasse MyClass Class. In der Tat, der Code des Beispiels, ich nie ein MyClass-Objekt instanziieren, ich beziehe mich nur auf die MyClass-Klasse selbst.

Ich habe ein paar weitere Tests durchgeführt und festgestellt, dass Klassenobjekte zumindest keine Konstruktoren zu haben scheinen, die normalerweise aus Objektunterklassen stammen. Wenn Sie einfach irgendwo in Ihrem Code new Class(); eingeben, wird dies gut demonstriert, aber Sie können dies weiter untersuchen, indem Sie die Eigenschaft .constructor und andere Tricks untersuchen. Aus diesem Grund sind Instanzen der Klasse Class bestenfalls Objekte der zweiten Klasse, da sie zur Laufzeit nicht erstellt werden können.

Zuerst vermutete ich, dass dies die genaue Ursache meiner ekligen VerifyError war. Ich glaube jedoch, dass es viele andere Elemente für eine Klasse gibt, die für unseren ActionScript-Code unsichtbar sind und die in der Klasse Class, der Function-Klasse oder an anderen merkwürdigen Stellen vorhanden sein können. Sicherlich, wenn der Flash Player versucht, auf einen der für die Erweiterung einer Basisklasse notwendigen zuzugreifen, und er existiert nicht (da Klasse möglicherweise ein ABC ist und somit bestimmte Elemente in einer normalen Klasse fehlen), könnte man durchaus erwarten um ein Out-of-Bounds zu sehen VerifyError.

Zusammengefasst scheint die Erweiterung der Class-Klasse derzeit unmöglich zu sein. Es scheint, dass die Class-Klasse nicht alle Qualitäten enthält, die die meisten anderen Top Level-Klassen von Object erben, obwohl dies schwierig zu testen ist.

Ich würde es vorziehen, ein spezifischeres Fehlermeldungsergebnis zu sehen, wenn man Klasse erweitert, aber im Moment gibt es keine solche Sache. Ich würde gerne sehen, dass einige Metaprogrammierungsfunktionen in ActionScript zurückgegeben werden. Für jetzt ist es gut genug, um schlüssig zu wissen, dass es zumindest auf diese Weise nicht gemacht werden kann.

+0

ABC steht in diesem Fall für ActionScript-Bytecode. Die von Ihnen gepostete Spur ist das ABC, das beim Auslösen der Ausnahme ausgeführt wird, wobei die letzte Zeile der Opcode "newclass" ist. Wenn Sie die AVM-Dokumente für eine neue Klasse überprüfen (http://www.adobe.com/devnet/actionscript/articles/avm2overview.pdf), sehen Sie, dass die Basisklassen (in diesem Fall Class und Object) aktiviert sein müssen der Stapel und ihre statischen Initialisierer werden ausgeführt. Vielleicht ist dies die Wurzel der Ausnahme - Klasse hat keinen statischen Initialisierer, und die Suche nach ihr verursacht einen Out-of-Bounds-Read. – tclem

+0

tclem, danke für den Link. Ich hatte keine Ahnung, dass sie ein solches Dokument zur Verfügung gestellt haben. Ich werde darüber lesen und meinen Beitrag mit dem, was ich lerne, überarbeiten. – ivanreese

5

Aus dem Livedoc im ersten Absatz heißt es Every Class object is an instance of the Class class. Daher wäre es ein Fehler, die Klasse zu erweitern, da jedes Klassenobjekt bereits eine Klasse ist.

sagte Sie a system that generates some templates, and then generates some objects based on those templates. Es klingt wie das, was Sie wirklich versuchen, eine Schnittstelle zu tun ist, erstellen.

Eine Schnittstelle sollte verwendet werden, wenn Sie Ihre Vorlage jede Implementierung bietet keine. Das heißt, Sie deklarieren eine Reihe von Feldern und Methoden, bieten jedoch keine Implementierung der Methoden. Sie würden eine solche Klasse wie folgt deklarieren:

public interface Foo { 
    function bar:void; 
} 

nun eine Klasse zu erstellen, die diese Schnittstelle implementiert Sie einfach die folgende tun.

Es ist möglich, dass eine Klasse mehrere Schnittstellen implementiert, während sie nur eine Klasse erweitern kann.

Wenn Sie jedoch jede Implementierung in Ihrer Vorlagenklasse bereitstellen möchten, ist es wahrscheinlich am besten, wenn Sie nur eine Klasse erstellen, die Gemeinsamkeiten zu den Unterklassen hat, und einfach die alte Vererbung verwenden.

Hoffe, das hilft.

+0

Matt, danke für deine Antwort. Ich werde die Frage ein wenig weiter klären, da Sie das Problem, wie ich es ziemlich gut dargestellt habe, behandelt haben, doch jetzt ist mir klar, dass ich den Verwendungszweck, den ich mir vorgenommen habe, nicht vollständig spezifiziert habe. Schnittstellen funktionieren in diesem Fall nicht, da eine Schnittstelle in Actionscript kein Objekt per se ist (obwohl es laut den Dokumenten ein Datentyp ist), es ist ein Konstrukt, das zum Standardisieren der öffentlichen Schnittstelle einer Klasse verwendet wird. Ich suche nach einer Objektdarstellung einer Klasse, die zur Laufzeit dynamisch manipuliert und instanziiert werden kann. – ivanreese

+0

Auch, re: Ihr erster Absatz: Warum wäre es ein Fehler? Ich sehe das nicht, obwohl es scheint, dass ich es erlebe (siehe: ABC-Fehler). Wenn jedes Objekt vom Typ Class eine Instanz der Class-Klasse ist, warum kann ich dann keine Unterklasse der Class-Klasse erstellen und dann Instanzen der Unterklasse erstellen, da sie immer noch die Class-Klasse in ihrer Abstammung haben? – ivanreese

+0

Zuletzt werde ich Ihre Antwort abstimmen, sobald ich 15 Wiederholungen habe. Da dies meine erste Frage überhaupt ist, und heute ist mein erster Tag, aktiv auf der Seite zu posten (obwohl ich ein langjähriger Fan und Leser gewesen bin), wird es ein wenig dauern, bevor ich den ganzen Weg an Bord bin und in der Lage, voll teilzunehmen. Nochmals vielen Dank. – ivanreese

Verwandte Themen