Objekt Eigenschaft bei Vererbung
Stefan
- javascript
0 Andreas Lindig0 Stefan
0 Siechfred0 Stefan0 Siechfred0 Andreas Lindig
Hallo allerseits,
ich möchte eine Objekt-Eigenschaft in Form eines Arrays benutzen. Das funktioniert aber nur, wenn diese Eigenschaft in der Objekt-Definition festgelegt wurde, nicht aber, wenn sie von einem übergeordneten Objekt vererbt wurde. Der folgende Code gibt für die Eigenschaft "Objekte" der Instanzen "Kind1" und "Kind2" beidesmal den String "Rassel" aus, es scheint also, als würden alle Instanzen auf denselben Wert gesetzt. Das ist aber nicht der Fall, wenn die Eigenschaft keine Arrayform hat, oder keine Vererbung vorliegt, wie beim "WAISE"-Objekt.
function ELTERN (Objekte, Alter){
this.Objekte = Objekte || ["leer"];
this.Alter = Alter || 30;
}
function KIND (irgendwas){
this.irgendwas = irgendwas;
}
KIND.prototype = new ELTERN;
Kind1 = new KIND;
Kind2 = new KIND;
Kind1.Objekte[0] = "Ball";
Kind1.Alter = 5;
Kind2.Objekte[0] = "Rassel";
Kind2.Alter = 10;
function WAISE (Objekte, Alter){
this.Objekte = Objekte || ["leer"];
this.Alter = Alter || 7;
}
Waise1 = new WAISE;
Waise1.Alter = 5;
Waise2 = new WAISE;
Waise2.Alter = 10;
Waise1.Objekte[0] = "Ball";
Waise2.Objekte[0] = "Rassel";
str1 = "Kind1: "+Kind1.Objekte[0]+", "+Kind1.Alter+"\nKind2: "+Kind2.Objekte[0]+", "+Kind2.Alter;
str2 = "Waise1: "+Waise1.Objekte[0]+", "+Waise1.Alter+"\nWaise2: "+Waise2.Objekte[0]+", "+Waise2.Alter;
alert(str1+"\n"+str2);
Kann mir jemand, der mehr Ahnung von OOP und JS hat als ich, sagen, woran das liegt? Bitte fragt auch nicht, wozu das gut sein soll, das Problem stellt sich mir nämlich nicht im Zusammenhang mit einem Webbrowser. Ich arbeite in der Audio-Entwicklungsumgebung MAX/MSP, die seit Kurzem eine Schnittstelle zu JS hat. Ich habe es nur auf eine in einem Webbrowser darstellbare Art reduziert.
Vielen Dank für jede Hilfe. Mit freundlichen Grüßen
Stefan
Hallo Stefan,
function ELTERN (Objekte, Alter){
this.Objekte = Objekte || ["leer"];
this.Alter = Alter || 30;
}function KIND (irgendwas){
this.irgendwas = irgendwas;
}KIND.prototype = new ELTERN;
DAS ist keine Vererbung. JS kennt keine Vererbung.
Wenn Du Dein Beispiel mal auf den relevanten Teil verkürzen könntest, würde ich auch weiterkucken. So ist mir das im Moment zu mühsam :-)
Gruß, Andreas
Hallo Andreas
DAS ist keine Vererbung. JS kennt keine Vererbung.
Ich bitte, sich nicht an der Terminologie zu stören. In Netscapes JS Core Guide, Chapter 8 gibt es immerhin einen Abschnitt über "Subclasses and Inheritance" und die Vererbung ist an einem Beispiel beschrieben.
Wenn Du Dein Beispiel mal auf den relevanten Teil verkürzen könntest, würde ich auch weiterkucken. So ist mir das im Moment zu mühsam :-)
Sorry, das ist bereits die Verkürzung. Kopier doch mal den Code in den <head> eines html Minimaldokuments und sag mir, warum 2 verschiedene Ergebnisse für Kind oder Waise vorkommen.
Danke
Stefan
Tag Stefan.
ich möchte eine Objekt-Eigenschaft in Form eines Arrays benutzen. Das funktioniert aber nur, wenn diese Eigenschaft in der Objekt-Definition festgelegt wurde, nicht aber, wenn sie von einem übergeordneten Objekt vererbt wurde. Der folgende Code gibt für die Eigenschaft "Objekte" der Instanzen "Kind1" und "Kind2" beidesmal den String "Rassel" aus, es scheint also, als würden alle Instanzen auf denselben Wert gesetzt. Das ist aber nicht der Fall, wenn die Eigenschaft keine Arrayform hat, oder keine Vererbung vorliegt, wie beim "WAISE"-Objekt.
Ja. Wenn du es so schreibst, wird das Objekt ELTERN nur einmal vererbt, nämlich auf das Objekt KIND. Damit steht es mit seinen Eigenschaften für alle KIND-Objekte genau einmal zur Verfügung. Änderst du eine vom Objekt ELTERN geerbte Eigenschaft, führt das zu dem von dir beschriebenen Ergebnis führt. Willst du für jedes KIND-Objekt auch ein dazu gehörendes ELTERN-Objekt haben, könnte es vom Ansatz her so aussehen:
function ELTERN (a, b){
this.Objekte = a || ["leer"];
this.Alter = b || 30;
}
function KIND (c, d, e){
this.ELTERN = new ELTERN(d, e);
this.irgendwas = c;
}
Das Ganze dann so aufgerufen:
Kind1 = new KIND("irgendwas", "Ball", 5);
Kind2 = new KIND("nochwas", Rassel", 10);
führt dann zu dem Ergebnis, das du haben möchtest. Ich hoffe, ich habe das jetzt richtig und verständlich erklärt :)
[dsf 3.6]
Siechfred
Hallo Siechfred,
danke für die Mühe, Du hast es auch gut erklärt. Leider ist das nicht mein Problem. Ich brauche tatsächlich nur eine ELTERN - Instanz für alle Kind Objekte.
Ja. Wenn du es so schreibst, wird das Objekt ELTERN nur einmal vererbt, nämlich auf das Objekt KIND. Damit steht es mit seinen Eigenschaften für alle KIND-Objekte genau einmal zur Verfügung. Änderst du eine vom Objekt ELTERN geerbte Eigenschaft, führt das zu dem von dir beschriebenen Ergebnis.
Stimmt nicht. Ich habe, um das auszuschließen die Eigenschaft "Alter" eingeführt. Sie wird ebenfalls von ELTERN geerbt, liegt aber nicht als Array vor. Da ist es möglich, individulellen KIND- Instanzen verschiedene Werte zuzuweisen. Der Unterschied liegt anscheinend nur darin, daß "Objekte" ein Array ist.
Danke trotzdem und nette Grüße
Stefan
Tag Stefan.
danke für die Mühe, Du hast es auch gut erklärt. Leider ist das nicht mein Problem. Ich brauche tatsächlich nur eine ELTERN - Instanz für alle Kind Objekte.
Dann verstehe ich dein Problem nicht.
Ja. Wenn du es so schreibst, wird das Objekt ELTERN nur einmal vererbt, nämlich auf das Objekt KIND. Damit steht es mit seinen Eigenschaften für alle KIND-Objekte genau einmal zur Verfügung. Änderst du eine vom Objekt ELTERN geerbte Eigenschaft, führt das zu dem von dir beschriebenen Ergebnis.
Stimmt nicht.
Stimmt doch :)
Projiziere meine Aussage auf das Array-Objekt, denn dieses ist - wie du schon vermutest - der Knackpunkt. Ich habe mir das Ganze nochmal angesehen und bin zu folgender Lösung gekommen:
function ELTERN (Objekte, Alter) {
this.Objekte = Objekte || ["leer"]
this.Alter = Alter || 30;
}
function KIND (irgendwas){
this.irgendwas = irgendwas;
}
KIND.prototype = new ELTERN;
Kind1 = new KIND;
Kind2 = new KIND;
// hier ist der Knackpunkt: erst hier wird Objekte zum Array
Kind1.Objekte = new Array("Ball","Rassel");
Kind1.Alter = 5;
Kind2.Objekte = new Array("Nuckel","Kreisel");
Kind2.Alter = 10;
alert("Kind1: "+Kind1.Objekte[0]+", "+Kind1.Objekte[1]+", "+Kind1.Alter+"\nKind2: "+Kind2.Objekte[0]+", "+Kind2.Objekte[1]+", "+Kind2.Alter);
Es bringt auch nichts, die Array-Definition in der ELTERN-Funktion unterzubringen. Das Problem ist genau das, was ich vermutet hatte, du erzeugst ein Array ELTERN.Objekte, auf das sämtliche KIND-Objekte Zugriff haben. Du willst aber vermutlich, dass jedes KIND ein eigenes Array ELTERN.Objekte bekommt.
[dsf 3.6]
Siechfred
Hallo Siechfred,
Du schreibst:
---wird das Objekt ELTERN nur einmal vererbt, nämlich auf das Objekt KIND. Damit steht es mit seinen Eigenschaften
für alle KIND-Objekte genau einmal zur Verfügung. Änderst du eine vom Objekt ELTERN geerbte Eigenschaft, führt
das zu dem von dir beschriebenen Ergebnis.
Warum aber bleibt dann die Alter-Eigenschaft für jede KIND-Instanz individuell, wenn es nur "einmal zur Verfügung" steht?
function ELTERN (Objekte, Alter) {
this.Objekte = Objekte || ["leer"]; // da fehlte das Semicolon (für die, die es nachbauen wollen)
this.Alter = Alter || 30;
}function KIND (irgendwas){
this.irgendwas = irgendwas;
}KIND.prototype = new ELTERN;
Kind1 = new KIND;
Kind2 = new KIND;// hier ist der Knackpunkt: erst hier wird Objekte zum Array
Interessant. Immerhin funktioniert das. Obwohl es mir nicht schlüssig vorkommt. Denn Du könntest an dieser Stelle schon, vor den nachfolgenden Zuweisungen mit
alert(Kind1.Objekte[0]);
die Ausgabe "leer" erreichen, was dem default-Wert aus ELTERN entspricht. Also muß es schon ein Array sein.
Kind1.Objekte = new Array("Ball","Rassel");
Kind1.Alter = 5;
Kind2.Objekte = new Array("Nuckel","Kreisel");
Kind2.Alter = 10;alert("Kind1: "+Kind1.Objekte[0]+", "+Kind1.Objekte[1]+", "+Kind1.Alter+"\nKind2: "+Kind2.Objekte[0]+", "+Kind2.Objekte[1]+", "+Kind2.Alter);
Es bringt auch nichts, die Array-Definition in der ELTERN-Funktion unterzubringen. Das Problem ist genau das, was ich vermutet hatte, du erzeugst ein Array ELTERN.Objekte, auf das sämtliche KIND-Objekte Zugriff haben. Du willst aber vermutlich, dass jedes KIND ein eigenes Array ELTERN.Objekte bekommt.
Ich wollte eigentlich nur eine Eigenshaft haben, die allen "Unterklassen" gemeinsam ist. In meinem tatsächlichen Fall gibt es sozusagen "mehrere Generationen" und ich wollte mir die Neudefinition immer der gleichen Eigernschaften sparen, was auch geht, solange es eben keine Arrays sind. Im Grunde genommen machst Du genau das in Deinem Beispiel.
Ich denke, ich werde das auch so ähnlich tun, womit Du mir sehr geholfen hast.
Ehrlich gesagt denke ich jetzt, daß das beschriebene Verhalten ein Bug in JS ist.
Danke und schöne Festtage
Stefan
Tag Stefan.
Warum aber bleibt dann die Alter-Eigenschaft für jede KIND-Instanz individuell, wenn es nur "einmal zur Verfügung" steht?
Weil Alter eine definierte Eigenschaft ist, Objekte hingegen ein Array-Objekt. Hier scheint die Vererbung fehl zu schlagen, wie Andreas schon schrieb.
Siechfred
Hallo,
Der Unterschied liegt anscheinend nur darin, daß "Objekte" ein Array ist.
nein. Der Unterschied ist, daß Du mit KIND.Alter dem KIND-Objekt eine neue Eigenschaft zuweist - sie ist NICHT mehr die aus dem Elternelement. Mit KIND.Objekte[0] geht das nicht, weil KIND.Objekte nicht existiert, deswegen sieht JS im prototype-Objekt nach, ob es dort eine Eigenschaft Objekte gibt. Sieh Dir mal die JS-Fehlermeldungen an. Du kannst z.B. sehr wohl KIND.Objekte = "dreirad" zuweisen. Aber das ist eine _neue_ Eigenschaft von KIND, nicht von ELTERN.
Vererbung ist Fehlanzeige.
Gruß, Andreas
Tag Andreas.
Der Unterschied ist, daß Du mit KIND.Alter dem KIND-Objekt eine neue Eigenschaft zuweist - sie ist NICHT mehr die aus dem Elternelement.
Doch, durch "KIND.prototype = new ELTERN" wird das ELTERN-Objekt mit all seinen Eigenschaften auf das KIND-Objekt vererbt. Somit hat das KIND-Objekt automatisch die Eigenschaften (ELTERN.)Objekte und (ELTERN.)Alter. Welche Werte diese Eigenschaften haben ist hier erstmal von untergeordneter Bedeutung.
Mit KIND.Objekte[0] geht das nicht, weil KIND.Objekte nicht existiert, deswegen sieht JS im prototype-Objekt nach, ob es dort eine Eigenschaft Objekte gibt.
Und wird dort fündig.
Sieh Dir mal die JS-Fehlermeldungen an.
Wie meinst du das? Es gibt in der JS-Konsole keinerlei Fehlermeldungen, Warnungen oder Hinweise.
Du kannst z.B. sehr wohl KIND.Objekte = "dreirad" zuweisen. Aber das ist eine _neue_ Eigenschaft von KIND, nicht von ELTERN.
Nein, es ist ein neuer Wert für die Eigenschaft Objekte, die das KIND-Objekt vom ELTERN-Objekt geerbt hat. Das Problem ist hier m.E. tatsächlich das anonyme Array. Ein typeof Kind1.Objekte ergibt "Object", nämlich ein (anonymes) Array-Objekt, erzeugt durch die Anweisung '["leer"]', macht man diese Klammern weg, ergibt eine Typenabfrage für die Eigenschaft Objekte den Typ "String". Was erreicht werden soll, ist wohl, dass KIND.Objekte ein individuelles Array-Objekt werden soll, und das erreicht man m.E. nur über den von mir in https://forum.selfhtml.org/?t=97151&m=591906 vorgeschlagenen Weg.
[dsf 3.6]
Siechfred
Hallo Andreas,
was Du schreibst, ist richtig, erklärt aber nicht, wie es kommt, daß 2x "Rassel " ausgegeben wird.
Danke trotzdem. Schöne Feiertage.
Stefan
Der Unterschied liegt anscheinend nur darin, daß "Objekte" ein Array ist.
nein. Der Unterschied ist, daß Du mit KIND.Alter dem KIND-Objekt eine neue Eigenschaft zuweist - sie ist NICHT mehr die aus dem Elternelement. Mit KIND.Objekte[0] geht das nicht, weil KIND.Objekte nicht existiert, deswegen sieht JS im prototype-Objekt nach, ob es dort eine Eigenschaft Objekte gibt. Sieh Dir mal die JS-Fehlermeldungen an. Du kannst z.B. sehr wohl KIND.Objekte = "dreirad" zuweisen. Aber das ist eine _neue_ Eigenschaft von KIND, nicht von ELTERN.
was Du schreibst, ist richtig, erklärt aber nicht, wie es kommt, daß 2x "Rassel " ausgegeben wird.
doch. Du überschreibst die prototyp-Eigenschaft .Objekte[0] mit dem Wert "Rassel". Diese Eigenschaft ist nach wie vor ein Element von ELTERN und deshalb nur einmal vorhanden - ähnlich wie eine Klassenvariable. Wer zuletzt überschreibt hat gewonnen und das ist bei Dir eben "Rassel". Wenn Du "Ball" und "Rassel" vertauscht bekommst Du 2x "Ball".
Gruß, Andreas