Prototypen

In den vorhergehenden Beispielen zu Klassen gab es drei Plätze um einem Objekt Eigenschaften zuzuweisen. Sie können Sie direkt der Klasse zuweisen, z.B. A.temp. Sie können temporäre Eigenschaften innerhalb des Klassenblocks { } benutzen, z.B. var x = 5; Zu guter letzt können Sie dem Objekt selbst ("this") Eigenschaften innerhalb des Konstruktors zuweisen während eine Instanz erstellt wird. Diese Eigenschaften sind Teil der neuen Instanz. Es mag viele Wege geben um eine Eigenschaft zu setzen, aber eine Sache können Sie nicht tun: Es gibt keinen Weg eine Eigenschaft zu definieren welche zur Klasse gehört, aber in einer Instanz verfügbar ist. Das mag vielleicht komisch klingen, also lassen Sie es uns genauer betrachten. Nehmen wir das einfache Beispiel mit der Klasse Hund:

Hund = function( )
{
this.beine = 4;
}
rover = new Hund( );
fido = new Hund( );
yeller = new Hund( );

Es mag so aussehen als gehöre die "this.beine" Eigenschaft zur Klasse Hund weil es dort zugewiesen wird. Es sieht so aus als wäre es einfach für alle Instanzen von Hund verfügbar gemacht worden und ist immer noch Bestandteil der Klasse - aber das ist nicht der Fall. Die "beine" Eigenschaft endet nur in den Instanzen, es gibt keine Möglichkeit sie über die Klasse anzusprechen (Hund.instance.beine, Hund.benji.beine, Hund.beine - keiner dieser Versuche klappt). Also ist es offensichtlich keine Eigenschaft der Klasse Hund, sondern eine Instanzeigenschaft (benji.legs, fido.legs ... sind OK). Was wäre wenn man sagt Hund.beine = 4 ? Würde es dann eine Klasseneigenschaft sein die den Instanzen zur Verfügung steht? Mit einigen Tricks können Instanzen (manchmal) auf diese Eigenschaft zugreifen, aber ist das auch wirklich korrekt? Soll benji die Klasse fragen müssen wieviel Beine er hat, oder sollte er es selbst wissen? Wenn benji einer bestimmten Hunderasse angehört, dann sollte Benhi alle Eigenschaften eines Hundes haben. - Es sollte automatisch passieren. Wenn wir schreiben Hund.beine = 4, dann bleibt benji.beine jedoch null. Was wir in diesem Fall benötigen nennt sich Prototyp Objekt.

Alle Klassen haben Prototypen die für alle Instanzen sichtbar sind. Es coexistiert an der Seite einer Klasse und beinhaltet Eigenschaften die für die Klasse relevant sind. Das nette daran ist, dass alle Instanzen dort automatisch nach Eigenschaften suchen. Natürlich checkt eine Instanz die eigenen Eigenschaften zuerst, es gibt keinen Grund einen Freund nach der Uhrzeit zu fragen wenn man selbst eine Uhr trägt. Die Instanz prüft sich selbst auf die Eigenschaft, und wenn sie nicht gefunden wird, sagt sie "Nunja, ich bin vom Typ Hund, also schauen wir mal ob Hunde diese Eigenschaft besitzen". Anschließend wird die Eigenschaft vom Prototyp der Klasse geholt. (Wow, ein sprechender Hund!)

Nun können wir alle Informationen über Hunde in die Klasse legen und in Instanzen alle Eigenschaften für jeden individuellen Hund. Es geht nur noch darum die Syntax zu lernen, aber das ist immer der einfachere Teil:

Hund = function( ){}
Hund.prototype.beine = 4;

rover = new Hund( );
fido = new Hund( );
yeller = new Hund( );

fido.puffyHair = true;

Nun sind alle Dinge dort, wo sie hingehören. Alle Hunde haben vier Beine, aber puffyHair ist eine Eigenschaft nur von fido. Das heißt nicht, dass andere Hunde nicht denselben Haarstil haben können, nur dass es eine spezielle Eigenschaft von fido ist, also keine generelle Regel für alle Hunde. Aber alle haben die "beine" Eigenschaft, obwohl diese von Hund.prototype.beine kommt und nicht von fido.beine. Das schöne daran ist, dass man auf den Prototypen "beine" genauso zugreifen kann wie auf jede andere Eigenschaft von fido. In Wirklichkeit weiß man nicht woher die Eigenschaft genau kommt, muss man auch nicht. Das heißt nicht, dass sie es nicht an den richtigen Ort platzieren wollen, nur dass Sie auf diese Eigenschaften genauso zugreifen können wie auf gewöhnliche Properties der Instanzen. Das ist alles wunderbar, allerdings schießt dies ein paar Löcher in unsere Karton-Metapher, die wir für Objekte benutzt haben. Lassen Sie uns das klarstellen. Man kann Objekte als Kartons/Container ansehen mit einer Liste des Inhalts darauf geklebt. Das stimmt immer noch. Innerhalb des Kartons ist nicht mehr genau das passiert, was man sich von gewöhnlichen Kartons erwartet. Dafür benötigen wir eine neue Metapher.

Vererbung funktioniert ein wenig wie übereinanderliegende Ebenen von Glas. Wenn Sie jemals Canada oder Finnland besucht haben haben Sie wahrscheinlich schon Dreischicht-Fensterglas gesehen. Sie isolieren so gut, dass Sie Ihr Haus schon fast beheizen. (Wenn Sie an Phoenix denken, benutzen Sie die Gläser eventuell um die Hitze draußen zu lassen). Was hier Sinn macht ist, wenn Sie diese Fenster ansehen können Sie nicht sofort feststellen aus wievielen Schichten sie bestehen. Viele Leute müssen zwar nur auf die Heizkostenabrechnung sehen um das herauszufinden, aber Heimwerker benutzen einen hervorragenden Trick. Sie halten ein Streichholz vor das Fenster und zählen die Reflexionen. Der Punkt ist, dass jeder Werker einen bestimmten Trick braucht. Also haben wir drei (oder mehr) Schichten von Glas - und im Hinterkopf wissen wir dass wir mehrere Schichten an Glas haben - aber wir können nur vom Hinsehen nicht feststellen, wieviele es sind. Das Letzte was Sie sich noch vorstellen können ist, kleine Papierschnipsel zwischen den Glasschichten hin und herzubewegen (versuchen Sie das nicht zuhause! - Es wird Ihr Fenster zerstören)
Sie können also Dinge in verschiedenen Ebenen bewegen, aber es wird immer so aussehen als wäre es auf der ersten Ebene. Wenn Sie ein Papier vor ein anderes bewegen (auf verschiedenen Ebenen!), dann sehen Sie nur das zu Ihnen nähere. Die vorderste Ebene ist eine besondere, sie kann leicht erreicht werden. Sie können Markierungen auf dem Papier machen, welches sich auf der Frontebene befindet. (modifizieren), neue Papiere hinzufügen (hinzufügen) oder Papiere wieder entfernen (löschen). Desto tiefer die Ebenen sind, desto weniger werden Sie geändert. Um Änderungen durchzuführen fügen Sie am besten ein neues Blatt Papier vor dem Glas hinzu, welches alle Ebenen dahinter überdeckt. Unter keinen Umständen können wir auf das Glas zeichnen. Das haben Sie bereits gelernt als Sie vier Jahre alt waren. Es scheint einiges zu sein, an das man sich erinnern muss, aber Actionscript regelt das alles für Sie.

Schauen Sie sich die beiden Illustrationen oben an, sehen Sie wie alles zusammenpasst wenn sie hintereinandergestellt werden. Gelb ist die erste Ebene, Orange die zweite, Purpur die dritte. Was würden Sie tun, um die mittlere Ebene zu modifizieren? Die Antwort ist, ein neues Papier davor zu kleben. Es ist zu umständlich wieder alle Fenster auseinander zu nehmen.

Eigenschaften eines Objekts sind also weniger wie das Zeichnen mit Kreide auf einer Tafel, sondern viel eher wie das ankleben von Dingen an ein Fenster. Das vorderste Fenster ist Ihre Instanz. Sie bekommt Eigenschaften beim Instanzieren. Dies geschieht mit Hilfe des "this" Schlüsselwortes. Nachdem die Instanz erstellt wurde können weitere Eigenschaften von Hand hinzugefügt werden, z.B. instanz.x = 5. Wir werden herausfinden, dass es noch mehrere Möglichkeiten gibt, wie Eigenschaften auf die Instanzebene gelangen. Die zweite Glasebene enthält Eigenschaften die zur Klasse gehören (die Klasse welche die Instanz erstellte) und welche in Class.prototype enthalten sind. Was auch immer jemand zur zweiten Ebene hinzufügt, es wird automatisch bei allen Instanzen der Klasse sichtbar sein. Um auf das Beispiel mit dem Hund zurückzukommen, wenn wir die puffyHair Eigenschaft zu Hund.prototype (zweite Glas-schicht) hinzufügen, dann hätten alle drei Hunde puffyHair.

Es gibt einen Punkt zu klären mit dem Fenster-schichten Modell: eine Eigenschaft die zu Class.prototype hinzugefügt wird scheint in allen Instanzen der Klasse auf. Heißt dass, dass alle Instanzen ihre eigene "Kopie" dieser Eigenschaft erhalten? Nein! Es ist in Wirklichkeit ein und diesselbe Eigenschaft für alle Instanzen. Vielleicht würden Sie das Ganze lieber visualisieren, in diesem Fall bricht jedoch die Metapher. Das Modell funktioniert wunderbar für eine einzelne Instanz, jedoch nicht für mehrere. Der Grund hierfür ist, dass Vererbung mehr ein menthales Klassifizierungssystem darstellt als ein physikalisches. Es ist nicht schwer nachzuvollziehen, dass alle Säugetiere nach derselben Definition von "Säugetier" zu klassifizieren sind und wenn sich die Definition ändert, sich auch die Definition eines jeden einzelnen Säugetiers ändert. Es heißt nicht, dass das Modell nicht mehr sinnvoll ist, da es sehr gut zur Beschreibung einer einzelnen Instanz dient, und es stellt das Überblenden (overriding) sehr schön dar, wie wir im nächsten Teil sehen werden.

 

 






Navigation
Einleitung · Objekte · Klassen · Instanzen · Lokal · Vererbung · Prototypen · Overriding · Overwrite · Protection · Argumente · Konstruktor · Methoden · __proto__ · arguments[] · callee · caller