Vererbung
Kambfhase
- javascript
Moin moin,
Ich hatte vor eine neue Klasse auf Basis eines Arrays zu schreiben, die ihn um einige Methoden erweitert.
function sdkSlice( arg){
Array.apply( this, arguments);
}
sdkSlice.prototype = new Array();
var a1 = new Array(8,17,26,35,44,53,62,71,80);
confirm( a1.toString());
var s2 = new sdkSlice(8,17,26,35,44,53,62,71,80);
confirm( s2.toString());
Leider spuckt mir mein Firefox "Fehler: Array.prototype.toString called on incompatible Object" aus. Mache ich etwas falsch, oder kann man von nativen Klassen nichts erben?
Gibt es sonst noch Alternativen?
MfG Hase
gruss Kambfhase,
Ich hatte vor eine neue Klasse auf Basis eines Arrays zu schreiben,
die ihn um einige Methoden erweitert.
<p class="korinthenkackermodus">
Du wolltest einen konstruktor schreiben, dessen objekte ihren kontext
sowohl beim instanziieren als auch beim methodenaufruf delegieren.
im ersten fall explizit an [[Array]] ueber eine der call-methoden [call]
bzw. [apply], im zweiten fall implizit ueber die methoden des leeren am
konstruktor haengenden array-objekt-prototypen.
</p>
function sdkSlice( arg){
Array.apply( this, arguments);
}
sdkSlice.prototype = new Array();var a1 = new Array(8,17,26,35,44,53,62,71,80);
confirm( a1.toString());
var s2 = new sdkSlice(8,17,26,35,44,53,62,71,80);
confirm( s2.toString());
sehr schoene schachzuege - aber ...
> Leider spuckt mir mein Firefox "Fehler: Array.prototype.toString
> called on incompatible Object" aus. Mache ich etwas falsch, oder
> kann man von nativen Klassen nichts erben?
doch, das ist in JavaScript sogar auf vielen wegen moeglich.
dummerweise sperren sich nun aber alle mir bekannten implementierungen
von [[Array]] gegen wirklich jeden versuch, auf direktem weg als basistyp
fuer selbstimplementierte listen jeglicher art zu dienen - selbst wenn man
alle huerden meistert, bekommt man die eigenschaft [length] bei keinem
browser unter kontrolle.
als einziger aber nicht wirklich gewollter bzw. ueberhaupt nicht eleganter
ausweg bliebe die implementierung solcher listen-konstruktoren als wrapper,
wobei man \*length\*, um browseruebergreifend kompatibel zu bleiben, leider
als [getLength]- bzw. [setLength]-methoden anlegen muesste.
> Gibt es sonst noch Alternativen?
Du koenntest den spiess umdrehen und Deine implementierung als »Behavior«,
als eine art »Interface« schreiben - also zuerst ein array-objekt erzeugen,
um dieses im nachhinein mit zusaetzlichem verhalten anzureichern:
~~~javascript
var SDKSliceBehavior = (function () { // *interface* : [SDKSliceBehavior]
this.sdkSlice = (function () { /*
code according to [this]
*/
});
});
var arr01 = [8, 17, 26, 35, 44, 53, 62, 71, 80];
var arr02 = [8, 17, 26, 35, 44, 53, 62, 71, 80];
SDKSliceBehavior.call(arr02); // applying the *interface*
alert(arr01.sdkSlice); // undefined
alert(arr02.sdkSlice); // function () { ... }
MfG Hase
so long - peterS. - pseliger@gmx.net
Erstmal danke für den schönen Post. Er hat mir im groben gut geholfen!
»» Ich hatte vor eine neue Klasse auf Basis eines Arrays zu schreiben,
»» die ihn um einige Methoden erweitert.
<p class="korinthenkackermodus">
Du wolltest einen konstruktor schreiben, dessen objekte ihren kontext
sowohl beim instanziieren als auch beim methodenaufruf delegieren.
im ersten fall explizit an [[Array]] ueber eine der call-methoden [call]
bzw. [apply], im zweiten fall implizit ueber die methoden des leeren am
konstruktor haengenden array-objekt-prototypen.
</p>
Ich habe noch viel mehr probiert um obiges zu erreichen. Der gepostete Code ist nur ein kleiner Teil meiner (gescheiterten) Versuche. BTW, gibt es einen Unterschied zwischen "call" und "apply" außer, dass sie anders heißen?
»» Gibt es sonst noch Alternativen?
Du koenntest den spiess umdrehen und Deine implementierung als »Behavior«,
als eine art »Interface« schreiben - also zuerst ein array-objekt erzeugen,
um dieses im nachhinein mit zusaetzlichem verhalten anzureichern:
/* insert code here */
Gute Idee. Ich habe es ein bißchen angepasst. Einziges Problem ist, dass ich beim Iteriren über den Slice auch die Methoden mitnehme.
for each( blub in aSlice) ... // Array + Methoden
aSlice.forEach( ...) // nur Array
Falls du da noch eine Lösung hättest, würde ich mich natürlich freuen. Ansonsten frimel ich mich da durch.
MfG Hase
hallo again Hase,
... BTW, gibt es einen Unterschied zwischen "call" und "apply" außer,
dass sie anders heißen?
beide methoden delegieren ein objekt an eine andere methode, die diesem
objekt nicht selber *gehoert*. diese wird dann im kontext des delegierten
objekts ausgefuehrt.
das jeweils erste argument fuer [call] bzw. [apply] steht fuer genau dieses
zu delegierende objekt; bei [call] steht jedes weitere argument eins zu eins
fuer den jeweiligen parameter der auf dieses objekt anzuwendenden methode,
waehrend [apply] als zweites und letztes argument nur eine liste aller
parameter der auf dieses objekt anzuwendenden methode akzeptiert.
... Einziges Problem ist, dass ich beim Iteriren über den Slice auch
die Methoden mitnehme.
for each( blub in aSlice) ... // Array + Methoden
aSlice.forEach( ...) // nur Array
so soll es doch auch sein ...
... `for (propertyName in obj)`{:.language-javascript} ... durchlaeuft alle iterierbaren eigenschaften
eines objekts unabhaengig davon, ob sie diesem objekt unmittelbar gehoeren
oder diesem nur ueber die verkettung aller objekt-prototypen zugeordnet werden
koennen, wohingegen die array-methode [forEach] natuerlich nur alle indizierten
member eines array-objekts durchlaeuft.
in Deinem fall gehoeren alle zusaetzlich ueber das [»Behavior/Interface«-muster](http://forum.de.selfhtml.org/archiv/2009/1/t182429/#m1207797)
auf das array-objekt applizierten oeffentlichen eigenschaften/methoden genau
diesem array-objekt und werden natuerlich von ... `for (propertyName in obj)`{:.language-javascript} ...
erfasst.
... wo genau siehst Du jetzt ein problem?
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](http://javascript.crockford.com/)
[ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:\]](http://www.peter.in-berlin.de/projekte/selfcode/?code=ie%3A%28+fl%3A%29+br%3A%3E+va%3A%28+ls%3A%26+fo%3A%29+rl%3A%29+n3%3B%7D+n4%3A%7D+ss%3A%7D+de%3A%B5+js%3A%7D+mo%3A%3F+zu%3A%5D)
Moin,
das jeweils erste argument fuer [call] bzw. [apply] steht fuer genau dieses
zu delegierende objekt; bei [call] steht jedes weitere argument eins zu eins
fuer den jeweiligen parameter der auf dieses objekt anzuwendenden methode,
waehrend [apply] als zweites und letztes argument nur eine liste aller
parameter der auf dieses objekt anzuwendenden methode akzeptiert.
Ah, ok. Ein kleiner aber feiner Unterschied.
... wo genau siehst Du jetzt ein problem?
Dass es für mich einiges an Mehrarbeit bedeutet, da ich dann irgendwie die Methoden rausfischen muss. Naja, wat mut, dat mut.
Gruß, Hase