Kambfhase: Vererbung

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

  1. 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

    --
    »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:]
    1. 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

      1. 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)
        
        1. 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