Wie alle, die Teil 4 meine Mootools-Tutorials gelesen haben, wissen, kann man mit dem Klassensystem von Mootools sehr komfortabel objektorientiert Javascript programmieren. Und wer auch Teil 5 gelesen hat, der weiß was einem das nützt – wenn man immer schön mootoolig denkt und arbeitet, kann man sich viel Mühe ersparen indem man immer weiter auf schon vorhandene Klassen aufbaut. Das geht auch recht problemlos, sofern man nicht den Inhalt einer in der Basisklasse schon vorhandenen Methode verändern will.

Ein Beispiel: Wir haben eine Klasse Huhn mit einer legeEi()-Methode, die den Ei-Counter der Huhn-Instanz um 1 erhöht. Wollte man nun die legeEi()-Methode verändern um zum Beispiel die neue Anzahl der Eier nach dem Legen auszugeben, ist man versucht das wie folgt zu machen:

// Mein Huhn legt Eier...
var Huhn = new Class({
    eier: 0,
    legeEi: function(){
        this.eier++;
    }
});

// ..soll mir aber auch mitteilen, wie viele schon gelegt sind!
Huhn.implement({
    legeEi: function(){
        alert(this.eier);
    }
});

var meinHuhn = new Huhn();
meinHuhn.legeEi(); // Geht schief, hier kommt immer 0 raus

Das geht aber schief (Demo), weil Huhn.implement die alte Methode komplett überschreibt – this.eier++ findet also gar nicht mehr statt. Nun könnte man natürlich die Funktionen der alten Methode einfach in sein Huhn.implement hineinkopieren …

Huhn.implement({
    legeEi: function(){
        this.eier++;  // Einfach aus der Basisklasse hinüberkopiert - auch doof.
        alert(this.eier);
    }
});

… was aber auch keine besonders gute Idee ist, denn schließlich könnte sich ja die Basisklasse ändern. Wenn das Power-Huhn in der Version 2.0 pro Arbeitsschritt zwei oder mehr Eier legen würde, würde unsere Copy-Page-Reimplementierung dieses Upgrade komplett kaputtmachen, da wir ja die komplette legeEi()-Funktionalität ersetzen und bei uns immer nur ein Ei gelegt wird.

Die Lösung für dieses Problem ist Class.Refactor. Hiermit verschwinden überschriebene Methoden nicht einfach, sondern sind unter this.previous weiter erreichbar. Damit löst sich unser Eierlegemethoden-Erweiterungsproblem in Rauch auf:

// Modifikation der legeEi-Methode via Class.Refactor
Huhn = Class.refactor(Huhn, {
    legeEi: function(){
        this.previous(); // Führe das ursprüngliche legeEi() aus
        alert(this.eier);
    }
});

Jetzt gibt meinHuhn.legeEi(); wie gewünscht 1 aus (Demo), da via this.previous() die ursprüngliche legeEi()-Methode ausgeführt und der Ei-Zähler um 1 erhöht wird … ohne jedes Copy-Paste-Gewürge! Und egal wie sich legeEi()-Methode der Basisklasse nun in Zukunft auch ändern mag, unsere Erweiterung ist immer auf dem aktuellen Stand. Class.Refactor sei Dank.