Stefan: Aufruf vererbter Methoden

Hallo,

ich hab ein bisschen rumgesucht im Forum, aber nicht wirklich das gefunden was ich suche. Ich werde es versuchen möglichst präzise zu erklären.

ich habe eine BasisKlasse namens Control. In dieser Klasse gibt es eine Methode Paint. Natürlich gibt es auch Klassen die von dieser Methode erben. In diesen wird die Methode Paint überschrieben. Allerdings möchte ich gerne, dass der Code der bereits in der Basisklassen Paint Methode definiert wurde auch ausgeführt wird.

function Control()
{
  this.Paint = function()
  {
    [mach was]
  }
}

function Label()
{
  this.Paint()
  {
    <baseclass>.Paint();
    [mach noch mehr]
  }
}
Label.prototype = new Control();

Ich hoffe es ist einigermaßen verständlich.
Grüße
Stefan

  1. ich habe eine BasisKlasse namens Control. In dieser Klasse gibt es eine Methode Paint. Natürlich gibt es auch Klassen die von dieser Methode erben. In diesen wird die Methode Paint überschrieben. Allerdings möchte ich gerne, dass der Code der bereits in der Basisklassen Paint Methode definiert wurde auch ausgeführt wird.

    Ich würde in der Basisklasse eine Referenz "auf sich selbst" speichern, also so ein Ansatz:

    function Control() {  
      this.objRef = this;  
      this.Paint = function() {  
        alert('in Control');  
      }  
    }  
      
    function Label() {  
      this.Paint()  
      {  
        this.objRef.Paint();  
        alert('in Label');  
      }  
    }
    

    Ansonsten sollte dieser Featureartikel für dich interessant sein:
    http://aktuell.de.selfhtml.org/artikel/javascript/organisation/

    Siechfred

    --
    [NaN]
  2. Hallo,

    function Control()
    {
      this.Paint = function()
      {
        [mach was]
      }
    }

    function Label()
    {
      this.Paint()
      {
        <baseclass>.Paint();
        [mach noch mehr]
      }
    }
    Label.prototype = new Control();

    Äh, du kannst natürlich schreiben:

    Label.prototype.Paint();

    Aber das hat nix mit prototypischer Vererbung zu tun, da könntest du auch einfach so ein Control-Objekt instantiieren, um auf die Paint-Methode Zugriff zu haben.

    Der Witz bei dieser bzw. Siechfreds Lösung (sie sind funktional identisch): this ist in Paint und Paint keinesfalls identisch. Wenn du in der Paint-Methode von Control etwas an this änderst, dann am Prototype! Ist ja auch klar, schließlich schreibst du:

    Label.prototype = new Control();

    Der Control-Konstruktor wird aufgerufen und dem erzeugten Objekt wird die Paint-Methode angehängt. Der Rückgabewert von new Control ist dieses neue Objekt wird in Label.prototyp gespeichert.

    Ist dir klar, was das heißt? Wenn ja, wirst du sehn, wie abwegig es ist... ;) Auf diese Weise hat Control.Paint auch keinen Zugriff auf Eigenschaften, die durch den Label-Konstruktor oder Label-Methoden gesetzt wurden. Und wenn du in Control.Paint eine Eigenschaft setzt, haben diese ALLE Lebel-Objekte - dank prototypischer Vererbung. Aber Label.Paint kann ebensowenig auf auf Eigenschaften zugreifen, die in Control.Paint gesetzt werden. Damit reitest du dich nur in Schwierigkeiten.

    Bei prototypischer Vererbung kannst du halt nicht zwei Methoden gleichen Namens haben. Normalerweise überschreibt die Methode, die im abgeleiteten Konstruktor (Label) definiert wird, die Methode, die im Basis-Konstruktor (Control) zugewiesen wird und über den Prototyp vererbt wird.

    Jetzt kann man sich natürlich andere Lösungen ausdenken, indem man die Basis-Paint speichert und dann die vererbte Methode überschreibt, um wiederum die zwischengespeicherte alte aufzurufen:

      
    function Control() {  
       this.Paint = function() {};  
    }  
    function Label() {  
       this.basePaint = this.Paint;  
       this.Paint = function () {  
          this.basePaint();  
       };  
    }  
    Label.prototype = new Control();  
    var myl = new Label;  
    myl.Paint();  
    
    

    Vorteil ist halt, dass man hier wirklich am selben Objekt operiert, wenn man this verwendet. Und man fummelt auch nicht am Prototyp von allen Label-Instanzen herum.

    Mathias

  3. gruss Stefan,

    ...
    ich habe eine BasisKlasse namens Control. In dieser Klasse gibt es
    eine Methode Paint. Natürlich gibt es auch Klassen die von dieser
    Methode erben. In diesen wird die Methode Paint überschrieben.
    Allerdings möchte ich gerne, dass der Code der bereits in der
    Basisklassen Paint Methode definiert wurde auch ausgeführt wird.

    obwohl ich davon ausgehe, dass Du die begriffe »Basisklasse« bzw.
    »Klasse« nur zur beschreibung Deines beispiels verwendest, bemuehe
    ich vor einer antwort nochmal das mantra:

    alle vererbungskonzepte in JavaScript sind klassenlos und basieren
    ausnahmslos auf delegation. die bei weitem am haeufigsten bemuehte
    vererbung basiert auf objekten, die als prototypen ueber konstruktor-
    funktionen referenziert werden (prototypische vererbung).
    auf der ebene *einfacher* und nicht in abhaengigkeit zueinander oder
    in anderer beziehung stehender objekte greift das konzept der schnitt-
    stellenvererbung viel direkter - genau dafuer haelt jedes [Function]-
    objekt die methoden [call] und [apply] in seinem arsenal vor.

    objekt-literale und schnittstellen-vererbung

    diese *woertelei* ist wichtig, da sich Dein beispiel mit den JavaScript
    zugrundeliegenden begriffen auf wunderbare weise genau an Dein von Dir
    gewuenschtes ziel brigen laesst.

    »» function Control()  
    
    > {  
    >   this.Paint = function()  
    >   {  
    >     [mach was]  
    >   }  
    > }  
    >   
    > function Label()  
    > {  
    >   this.Paint()  
    >   {  
    >     <baseclass>.Paint();  
    >     [mach noch mehr]  
    >   }  
    > }  
    > Label.prototype = new Control();
    
    
    var Control = function () {  
      
    //falls [[Control]] selbst ein objekt als [prototype]n referenziert:  
      this.constructor = arguments.callee;  
      
      this.status = "[object Control]";  
      
      this.paint = function () {  
      
      //Dein: [mach was]  
        alert("executing [object Control].paint :\n[this].status : " + this.status); // [1]  
      };  
    };  
      
    var Label = function () {  
      
    //da [[Label]] selbst ein [Control]-objekt als [prototype]n referenziert:  
      this.constructor = arguments.callee;  
      
      this.status = "[object Label]";  
      
      this.paint = function () { //  
      
      //(new Control()).paint.apply(this); // aber da es sich hier um den prototypen handelt:  
      
        this.constructor.prototype.paint.apply(this); // [2] delegation - Dein: <baseclass>.Paint()  
      
      // Dein: [mach noch mehr]  
        alert("executing [object Label].paint :\n[this].status : " + this.status); // [3]  
      };  
    };  
    Label.prototype = new Control();  
      
      
    var myControl = new Control();  
    var myLabel = new Label();  
      
      
    myControl.paint(); // executing [object Control].paint ... [this].status : [object Control] // [1]  
    myLabel.paint();   // executing [object Control].paint ... [this].status : [object Label]   // [2]  
                       // executing [object Label].paint   ... [this].status : [object Label]   // [3]
    

    dabei realisiert [2] das von Dir gewuenschte »<baseclass>.Paint();«, indem es die [paint]-methode
    des als objekt-prototypen *vererbten*/referenzierten [Control]-objekts im kontext eines [Label]-
    objekts aufruft.

    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:]