gruss felix12,
Irgendwie seltsam, das entspricht nicht dem was du wolltest.
Struppi.
Hallo Struppi!
Ja da hast du recht deine Lösung entspricht dem, was mir ursprünglich
am Herzen Lag, :) und ich bin dir auch sehr dankbar für deine Hilfe,
denn ich bin dadurch ein ganzes Stück weiter gekommen :)Aber ich interpretiere Peters Beispiel so, das eine Wrapper Funktion
die eigentliche Haupt-Klasse (in seinem beispiel cnstr) kapselt und
diese Hauptklasse auch nicht instanziert wird! Nur die Wrapper Klasse
wird instanziert! :)
wiederholung des beispielcodes:
var SomeConstructor = (function () { // kind of *private static* wrapper function
var hallo = "hallo";
var cnstr = (function () {/*
code */
});
cnstr.getHallo = (function () {
return hallo;
});
return cnstr;
})();
var obj = new SomeConstructor();
alert(obj.hallo); // [undefined]
alert(obj.getHallo); // [undefined]
alert(SomeConstructor.getHallo()); // "hallo"
/*
copy und paste nach : [[link:http://jconsole.com/]]
*/
... die eigentliche Haupt-Klasse (in seinem beispiel cnstr) ... ««
[cnstr] ist eine konstruktor-funktion. JavaScript ist klassenlos!
... und diese ... auch nicht instanziert wird! ... ««
[cnstr] wird tatsaechlich noch nicht instanziiert, dieser konstruktor
wird vom umschliessenden anonymen funktionsobjekt (dem wrapper) an die
variable [SomeConstructor] zurueckgegeben
... Nur die Wrapper Klasse wird instanziert! :) ... ««
nein - die einzige stelle, an der im beispiel ueberhaupt irgendwas
instanziiert wird, sieht so aus: var obj = new SomeConstructor();
das anonyme, den konstruktor umschliessende funktionsobjekt (der wrapper)
wird in einem ritt initialisiert und aufgerufen. der rueckgabewert dieser
funktion ist ein weiteres funktionsobjekt - der konstruktor, welcher dann
schlussendlich auf [SomeConstructor] abgebildet wird.
warum nun »SomeConstructor.getHallo
« als *public static* methode zugriff
auf das *private static* [hallo] hat, werde ich sofort und nur indirekt
in einem kurzen abriss des sprachkonzepts erlaeutern:
in JavaScript ist alles objekt ausser den primitiven werten [undefined]
und [null] sowie [string], [number] und [boolean]. auch funktionen sind
objekte. zusaetzlich zur ueblichen name/wert struktur, speichern diese
adressraeume anweisungen, die explizit durch anwendung einer der zwei
call-methoden [call] bzw. [apply] oder aber ueber den aufruf des call-
operators »()« ausgefuehrt werden.
darueber hinaus unterstuetzt JavaScript rekursion und gegenseitige
rekursion, sowie weitere paradigmen der funktionalen programmierung.
mit dieser ausrichtung des sprachkonzepts wird JavaScript zu einer
multiparadigmensprache, in der es sich sowohl rein prozedural - durch
rueckgabewertfreie funktionen, die ausschliesslich auf globalen
variablen arbeiten - programmieren laesst, als auch streng funktional
bzw. in allen moeglichen schattierungen dazwischen. den anforderungen
an objektorientierte sprachen wird JavaScript dadurch gerecht, dass
z.b. datenkapselung auf eine dem funktionalen programmierkonzept
zueigene weise stattfindet:
funktionen in JavaScript manifestieren sich im programmspeicher als
eigene adressraeume. gaengige deutsche bezeichnungen, um etwas ueber
die hardware-relevante arbeitsweise in erfahrung zu bringen, waeren
»unterprogramm« und »stapelspeicher«. im englischen gibt es die meiner
meinung nach eingaengigeren begriffe »call stack« bzw. »function stack«.
salopp umschrieben:
die lokalen variablen einer funktion sind von ausserhalb dieses sie
einschliessenden adressraumes nicht adressierbar. werden funktionen
nur geschickt genug verschachtelt, koennen sich deren lokale variablen,
obwohl von aussen immer noch nicht zugaenglich, trotzdem durch die
adressraeume hindurch referenzieren. und ... solange referenzen von
noch *lebenden* objekten in eine eigentlich schon abgearbeitete
funktion hinein bestehen, wird diese nicht von der automatischen
speicherbereinigung (garbage collection) erfasst.
instanzen eines bestimmten objekttyps werden ueber den gemeinsamen
aufruf von »new« operator und konstruktorfunktion erzeugt. innerhalb
eines konstruktors zeigt der operator »this« (wenn vorhanden) dabei
auf die oeffentlichen eigenschaften der erzeugten objektinstanz.
zu objektinstanzen und datenkapselung kaeme dann noch die vererbung,
welche in JavaScript in jedem fall durch delegation geschieht. schon
die ueber [[Function]] referenzierten methoden [apply] und [call]
ermoeglichen es einem objekt, die methoden eines anderen objekts zu
*borgen* und im eigenen kontext auszufuehren, ohne diese methoden
selbst besitzen zu muessen.
der [prototype] eines jeden konstruktors und die ueber ihn
referenzierbaren eigenschaften und methoden erweitern und
verfeinern nur das gerade angesprochene delegationskonzept.
in JavaScript waere man deshalb geradezu dazu verpflichtet,
objektkomposition auf basis wohldefinierter schnittstellen
als nativen - weil durch das sprachkonzept vorgegebenen -
vererbungsmechanismus direkt einzusetzen, statt zu versuchen,
klassenvererbung auf den gerade genannten grundlagen zu emulieren.
(
- siehe Gamma, Helm, Johnson, Vlissides ["Gang of Four"] :
"Entwurfsmuster - Elemente wiederverwendbarer objektorientierter
Software", S. 23 ff "Klassen- versus Schnittstellenvererbung" -
deutsche uebersetzung des amerikanischen orginals "Desig Patterns:
Elements of Reusable Object-Oriented Software"
- siehe auch: »JavaScript - Die am häufigsten mißverstandene Programmiersprache der Welt«
)
auch *klassen*-basierte mehrfachvererbung laesst sich in
JavaScript relativ unkompliziert nachbauen.
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:]