Aufruf vererbter Methoden
Stefan
- javascript
Hallo,
ich hab ein bisschen rumgesucht im Forum, aber nicht wirklich das gefunden was ich suche. Ich werde es versuchen möglichst präzise zu erklären.
ich habe eine BasisKlasse namens Control. In dieser Klasse gibt es eine Methode Paint. Natürlich gibt es auch Klassen die von dieser Methode erben. In diesen wird die Methode Paint überschrieben. Allerdings möchte ich gerne, dass der Code der bereits in der Basisklassen Paint Methode definiert wurde auch ausgeführt wird.
function Control()
{
this.Paint = function()
{
[mach was]
}
}
function Label()
{
this.Paint()
{
<baseclass>.Paint();
[mach noch mehr]
}
}
Label.prototype = new Control();
Ich hoffe es ist einigermaßen verständlich.
Grüße
Stefan
ich habe eine BasisKlasse namens Control. In dieser Klasse gibt es eine Methode Paint. Natürlich gibt es auch Klassen die von dieser Methode erben. In diesen wird die Methode Paint überschrieben. Allerdings möchte ich gerne, dass der Code der bereits in der Basisklassen Paint Methode definiert wurde auch ausgeführt wird.
Ich würde in der Basisklasse eine Referenz "auf sich selbst" speichern, also so ein Ansatz:
function Control() {
this.objRef = this;
this.Paint = function() {
alert('in Control');
}
}
function Label() {
this.Paint()
{
this.objRef.Paint();
alert('in Label');
}
}
Ansonsten sollte dieser Featureartikel für dich interessant sein:
http://aktuell.de.selfhtml.org/artikel/javascript/organisation/
Siechfred
Hallo,
function Control()
{
this.Paint = function()
{
[mach was]
}
}function Label()
{
this.Paint()
{
<baseclass>.Paint();
[mach noch mehr]
}
}
Label.prototype = new Control();
Äh, du kannst natürlich schreiben:
Label.prototype.Paint();
Aber das hat nix mit prototypischer Vererbung zu tun, da könntest du auch einfach so ein Control-Objekt instantiieren, um auf die Paint-Methode Zugriff zu haben.
Der Witz bei dieser bzw. Siechfreds Lösung (sie sind funktional identisch): this ist in Paint und Paint keinesfalls identisch. Wenn du in der Paint-Methode von Control etwas an this änderst, dann am Prototype! Ist ja auch klar, schließlich schreibst du:
Label.prototype = new Control();
Der Control-Konstruktor wird aufgerufen und dem erzeugten Objekt wird die Paint-Methode angehängt. Der Rückgabewert von new Control ist dieses neue Objekt wird in Label.prototyp gespeichert.
Ist dir klar, was das heißt? Wenn ja, wirst du sehn, wie abwegig es ist... ;) Auf diese Weise hat Control.Paint auch keinen Zugriff auf Eigenschaften, die durch den Label-Konstruktor oder Label-Methoden gesetzt wurden. Und wenn du in Control.Paint eine Eigenschaft setzt, haben diese ALLE Lebel-Objekte - dank prototypischer Vererbung. Aber Label.Paint kann ebensowenig auf auf Eigenschaften zugreifen, die in Control.Paint gesetzt werden. Damit reitest du dich nur in Schwierigkeiten.
Bei prototypischer Vererbung kannst du halt nicht zwei Methoden gleichen Namens haben. Normalerweise überschreibt die Methode, die im abgeleiteten Konstruktor (Label) definiert wird, die Methode, die im Basis-Konstruktor (Control) zugewiesen wird und über den Prototyp vererbt wird.
Jetzt kann man sich natürlich andere Lösungen ausdenken, indem man die Basis-Paint speichert und dann die vererbte Methode überschreibt, um wiederum die zwischengespeicherte alte aufzurufen:
function Control() {
this.Paint = function() {};
}
function Label() {
this.basePaint = this.Paint;
this.Paint = function () {
this.basePaint();
};
}
Label.prototype = new Control();
var myl = new Label;
myl.Paint();
Vorteil ist halt, dass man hier wirklich am selben Objekt operiert, wenn man this verwendet. Und man fummelt auch nicht am Prototyp von allen Label-Instanzen herum.
Mathias
gruss Stefan,
...
ich habe eine BasisKlasse namens Control. In dieser Klasse gibt es
eine Methode Paint. Natürlich gibt es auch Klassen die von dieser
Methode erben. In diesen wird die Methode Paint überschrieben.
Allerdings möchte ich gerne, dass der Code der bereits in der
Basisklassen Paint Methode definiert wurde auch ausgeführt wird.
obwohl ich davon ausgehe, dass Du die begriffe »Basisklasse« bzw.
»Klasse« nur zur beschreibung Deines beispiels verwendest, bemuehe
ich vor einer antwort nochmal das mantra:
alle vererbungskonzepte in JavaScript sind klassenlos und basieren
ausnahmslos auf delegation. die bei weitem am haeufigsten bemuehte
vererbung basiert auf objekten, die als prototypen ueber konstruktor-
funktionen referenziert werden (prototypische vererbung).
auf der ebene *einfacher* und nicht in abhaengigkeit zueinander oder
in anderer beziehung stehender objekte greift das konzept der schnitt-
stellenvererbung viel direkter - genau dafuer haelt jedes [Function]
-
objekt die methoden [call]
und [apply]
in seinem arsenal vor.
objekt-literale und schnittstellen-vererbung
diese *woertelei* ist wichtig, da sich Dein beispiel mit den JavaScript
zugrundeliegenden begriffen auf wunderbare weise genau an Dein von Dir
gewuenschtes ziel brigen laesst.
»» function Control()
> {
> this.Paint = function()
> {
> [mach was]
> }
> }
>
> function Label()
> {
> this.Paint()
> {
> <baseclass>.Paint();
> [mach noch mehr]
> }
> }
> Label.prototype = new Control();
var Control = function () {
//falls [[Control]] selbst ein objekt als [prototype]n referenziert:
this.constructor = arguments.callee;
this.status = "[object Control]";
this.paint = function () {
//Dein: [mach was]
alert("executing [object Control].paint :\n[this].status : " + this.status); // [1]
};
};
var Label = function () {
//da [[Label]] selbst ein [Control]-objekt als [prototype]n referenziert:
this.constructor = arguments.callee;
this.status = "[object Label]";
this.paint = function () { //
//(new Control()).paint.apply(this); // aber da es sich hier um den prototypen handelt:
this.constructor.prototype.paint.apply(this); // [2] delegation - Dein: <baseclass>.Paint()
// Dein: [mach noch mehr]
alert("executing [object Label].paint :\n[this].status : " + this.status); // [3]
};
};
Label.prototype = new Control();
var myControl = new Control();
var myLabel = new Label();
myControl.paint(); // executing [object Control].paint ... [this].status : [object Control] // [1]
myLabel.paint(); // executing [object Control].paint ... [this].status : [object Label] // [2]
// executing [object Label].paint ... [this].status : [object Label] // [3]
dabei realisiert [2] das von Dir gewuenschte »<baseclass>.Paint();
«, indem es die [paint]
-methode
des als objekt-prototypen *vererbten*/referenzierten [Control]
-objekts im kontext eines [Label]
-
objekts aufruft.
so long - peterS. - pseliger@gmx.net