gruss Christoph,
Wie baut man denn in JavaScript *nur mit Bordmitteln* Vererbungs_hierarchien_?
so wie bereits im meinereinigen definitionsversuch beschrieben:
» Vererbung wiederum erfolgt in JavaScript ausschließlich über Delegation;
entweder direkt über eine der call-Methoden oder implizit über den Objekt-
Prototypen eines jeden Objekt-Konstruktors. Letztgenannter leistet dabei
die Abstraktion zur Vererbung (im Sinne von *ist ein*), während die zuerst
angesprochenen Methoden der Umsetzung des Aggregationskonzepts (*hat ein*)
dienlich sind.«
In Self ist es einfach möglich, eine Vererbungshierarchie mit Tiefen > 1 zu bauen,
in JavaScript nicht.
warum denn nicht, dafuer kann man doch jedem konstruktor ein prototypisches
objekt zur seite stellen - das von Dir kritisierte *constructor.prototype*.
hier mal ein beispiel, welches eine prototypische vererbungskette ueber folgende
konstruktoren aubaut: [[Mamal]] --> [[CanisLupus]] --> [[CanisCanis]], wobei eine
instanz von [[Mamal]] der prototyp von [[CanisLupus]] ist, und ein [CanisLupus]-
objekt wiederum den prototypen von [[CanisCanis]] stellt.
die saueger-abstraktion stellt die atmung bereit. die wolfs-abstraktion erbt
die atmung von einem saeuger-objekt und stellt sicher, dass reviere markiert
werden koennen. die hunde-abstraktion wiederum erbt von einer wolfs-instanz
und will ein potentielles herrchen mit stoeckchenholen gluecklich machen.
ausserdem gibt es noch ausgabefunktionalitaet, die in keinen der genannten
konstruktoren nativ eingebaut ist. damit diese aber trotzdem jedem objekt
zur verfuegung steht und nicht frei herumschwebt, wird sie in eine art
interface verpackt, welches einmalig von [[Mamal]] implementiert wird.
den beispielcode lasse man dann bitte durch copy und paste auf die jconsole los:
var OutputInterface = (function () {
var constr;
if (typeof print == "function") {
constr = (function () {
this.trace = (function (str) {
print(str);
});
});
} else {
constr = (function () {
this.trace = (function (str) {
document.title = str;
});
});
}
return constr;
})();
var Mamal = (function () {
OutputInterface.call(this);
var timeoutIdBreathing;
var self = this;
var breathIn = (function () {
clearTimeout(timeoutIdBreathing);/*
document.title = "... breath in ...";
if (print) {print("... breath in ...");}*/
self.trace("... breath in ...");
timeoutIdBreathing = setTimeout(breathOut, 1500);
});
var breathOut = (function () {
clearTimeout(timeoutIdBreathing);/*
document.title = "... breath out ...";
if (print) {print("... breath out ...");}*/
self.trace("... breath out ...");
timeoutIdBreathing = setTimeout(breathIn, 1500);
});
this.justBreath = (function () {
breathIn();
});
this.holdBreath = (function () {
clearTimeout(timeoutIdBreathing);/*
document.title = "... breathing on hold ...";
if (print) {print("... breathing on hold ...");}*/
self.trace("... breathing on hold ...");
});
breathIn();
});/*
var myMamal = new Mamal;*/
var CanisLupus = (function () {
var constr = (function () {
var timeoutIdMarking;
var self = this;
var markingTerritory = (function () {
clearTimeout(timeoutIdMarking);/*
document.title = "... marking territory !..";
if (print) {print("... marking territory !..");}*/
self.trace("... marking territory !..");
timeoutIdMarking = setTimeout(markingTerritory, 10500);
});
this.goingToMarkTerritory = (function () {
markingTerritory();
});
this.stopMarkingTerritory = (function () {
clearTimeout(timeoutIdMarking);/*
document.title = "... marking territory stopped ...";
if (print) {print("... marking territory stopped ...");}*/
self.trace("... marking territory stopped ...");
});
});
constr.prototype = new Mamal;
constr.prototype.holdBreath();
return constr;
})();/*
var myWolf = new CanisLupus;
setTimeout(myWolf.justBreath, 5000);
setTimeout(myWolf.holdBreath, 60000);
setTimeout(myWolf.goingToMarkTerritory, 1000);
setTimeout(myWolf.stopMarkingTerritory, 51500);\*/
var CanisCanis = (function () {
var constr = (function () {
var timeoutIdRetrieving;
var self = this;
var goGetIt = (function () {
clearTimeout(timeoutIdRetrieving);/*
document.title = "... run and jump for stick ...";
if (print) {print("... run and jump for stick ...");}*/
self.trace("... run and jump for stick ...");
timeoutIdRetrieving = setTimeout(goGetIt, 13300);
});
this.goingToRetrieveStick = (function () {
goGetIt();
});
this.stopRetrievingStick = (function () {
clearTimeout(timeoutIdRetrieving);/*
document.title = "... retrieving stopped ...";
if (print) {print("... retrieving stopped ...");}*/
self.trace("... retrieving stopped ...");
});
});
constr.prototype = new CanisLupus;
return constr;
})();
var myDog = new CanisCanis;
setTimeout(myDog.justBreath, 5000);
setTimeout(myDog.holdBreath, 60000);
setTimeout(myDog.goingToMarkTerritory, 1000);
setTimeout(myDog.stopMarkingTerritory, 51500);
setTimeout(myDog.goingToRetrieveStick, 1500);
setTimeout(myDog.stopRetrievingStick, 53600);
im uebrigen laesst sich in JavaScript sogar mehrfachvererbung abbilden.
in welchen sprachen der OOP wird man denn dazu gezwungen 00 zu programmieren?
und dass mein ich nicht als theoretischen scheingegenargument. OO ist eine denke,
ein geistiger werkzeugkasten, um komplexe probleme moeglichst effizient zu loesen.
jede sprache, die es mir ermoeglicht, aufgaben auf dem wege der OOP zu loesen,
darf auch als sprache der OO bezeichnet werden.Also ist laut deinen Aussagen C eine OO-Sprache. Gewagt.
ich weiss, aber meine intension dahinter ist doch offensichtlich, ... wahrnehmungsbrillen
fuer das sprachkonzept von JavaScript zu verteilen.
was ist an schnittstellenvererbung und objektkomposition nicht OO?
Vielleicht habe ich nur noch nicht herausgefunden, wie man in JavaScript objektorientiert
programmiert? Meinst du mit Schnittstellenprogrammierung/Objektkomposition, dass man sich
zunächst ein Schnittstellen-Objekt mit geeigneten Methoden baut und diese dann jedem Objekt,
dass dies Schnittstelle implementiert, (bzw. dem Prototyp dessen Konstruktors) hinzufügt?
ja, aber einen konstruktor in seinem einsatz so umzubiegen, dass er dem konzept der interfaces
genuegt, ist nur eine der moeglichkeiten. delegation ist, wie schon gezeigt, auch auf direktem
weg ueber [call] und [apply] - und das nicht nur auf reiner objektbasis - moeglich.
Allerdings bietet JavaScript keine syntaktische Unterstützung für diesen Programmierstil ...
doch, das obige bsp. sollte das gegenteil beweisen.
... (was sich natürlich problemlos in 3 Zeilen Code beheben lässt), aber damit wären wir
wieder beim Argument, dass auch in C objektorientiert programmiert werden kann, nur halt
ohne nette Syntax.
die nette syntax zaehlt aber nicht als argument ;-)
In meinen Augen sind nur die folgenden Alternativen konsistent:
1. C ist keine OO-Sprache, JavaScript ist OO-Sprache (aber weder eine reine noch eine klassische)
2. C ist OO-Sprache, JavaScript ist reine OO-SpracheIch tendiere stark zu 1.
fuer 1) breche ich hier doch die ganze zeit immer wieder eine neue lanze.
so long - peterS. - pseliger@gmx.net
»Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]