PHP Blogger

Startseite Schreib mir ne Mail! RSS Abo Webnews

Vererben oder dekorieren?

Mich lässt der Artikel von Stefan nicht in Ruhe. Ihm ging es eigentlich um den Einsatz der Mehrfachvererbung und wie sinnvoll sie ist. Die Beispiele, die er von Corsin übernommen hat, sind recht wackelig und mein Vorschlag war, sie besser mit dem Dekoratormuster zu “erschlagen” als durch die Gegend zu vererben.

Ich möchte keinen langweilen, jeder hat sich damit bestimmt schon ausreichend beschäftigt, aber beide Methoden haben Ihre Vorteile und ich möchte jede Technik kurz anreissen, denn ich denke es ist sinnvoll, wenn man sich beider Techniken bewusst ist.

Vererbung

Wie es in Wikipedia ganz schön beschrieben ist, dient die Vererbung dazu, artverwandte Klassen von einander abzuleiten und mit jeder Klassenhierarchie-Ebene weiter zu verfeinern und  zu spezifizieren. Ein Beispiel macht klar, was ich meine:

Fahrzeug > Vierrädriges Fahrzeug > Automobil > Mini-Van > Opel Zafira > Opel Zafira OPC (Modell)

Bei der Vererbung werden für jede Stufe die Eigenschaften der Stufen vorher übernommen, eventuell neu definiert und mit neuen Eigenschaften angereichert. Hier nochmal ein Beispiel als Liste:

  • Fahrzeug: Fahrgestell und Lenkrad
  • Vierrädriges Fahrzeug: 2 Achsen mit 2 Rädern
  • Automobil: Motor und Abgasanlage
  • Mini-Van: Hoher Aufbau, 5 Sitze
  • Opel-Zafira: 2 Zusätzliche Sitze
  • Opel-Zafira OPC: Sport-Elemente

Die letzte Klassendefinition hat alle Elemente, die auch das Basis-Fahrzeug und die Modelle dazwischen eingebracht haben. Der Vorteil liegt auf der Hand: Man kann bestimmte Verhaltensweisen, Eigenschaften und Muster in ähnlichen Klassen wiederverwenden. Es gibt nur einen Ort, an dem sie definiert sind und entsprechend einfach ist ein Update.

Oder auch nicht - denn je komplexer der Vererbungshierarchie-Baum ist, um so schwieriger ist es, Elemente niedrig gelevelter Klassen einzuführen und gleichzeitig die Schnittstellen bei zu behalten.

Dazu kommt, das der Opel Zafira vielleicht Elemente hat, die er von einer niedrigeren Ebene geerbt hat, die er gar nicht mehr benötigt - z.B. ein Ersatzrad. Dafür hat er ein Reifenkit.

Und noch ein Problem: Die Klassendefinitionen sind mehr oder minder statisch. Das heisst, das man an der Funktionalität einer Klasse zur Laufzeit relativ wenig ändern kann, es sei denn durch Ausnahmen - durch die eine Klasse nicht gerade übersichtlicher wird.

Dekoratoren

Hier gehts nicht um Schaufenster - eher um Torten. Stell Dir einen leckeren Obstkuchen vor: Unten Biskuitteig, darauf eine dünne Schicht Pudding, jetzt die Erdbeeren, Kirschen, Bananen und Mandarinen. Zum Schluss noch einen Schlag Sahne ;) Hmmm lecker…

Was so schmackhaft klingt, ist der Versuch, Dir das Dekoratormuster schmackhaft zu machen. Man kann es mit PHP ebenso gut wie mit jeder anderen Programmiersprache einsetzen. Und ich wette, dass es sogar schon Menschen verwendet haben, die nicht wussten das sie es tun ;)

Der Vorteil ist, dass man die Kuchendeko auch zur “Laufzeit” austauschen kann *lach* Wer mag, macht dann Bananen runter und Pfirsiche drauf… Okay, programmiertechnisch hat man die Möglichkeit, Objekte gegen andere auszutauschen, die sinnvollerweise eine ähnliche oder die gleiche Schnittstelle verwenden.

Beispiel:

$auto->setReifenReparaturObjekt($ersatzRadMontierKit);
$auto->wiederFahrbarMachen();

Die Funktion “wiederFahrbarMachen” macht vielleicht folgende Aktionen:

function wiederFahrbarMachen()
{
  $this->reifenReparaturObjekt->bereiteReparaturVor();
  $this->reifenReparaturObjekt->fuehreReparaturDurch();
  $this->reifenReparaturObjekt->schliesseReparaturAb();
}

Das Reifenreparaturobjekt (im Moment das Ersatzrad-Objekt) macht in diesem Fall folgendes: Es hebt mit dem Wagenheber das Auto an, montiert das Rad ab, montiert das Reserverad, lässt das Auto mit dem Wagenheber wieder runter, packt alles in den Kofferraum, was es nicht benötigt und fertig.

Hätte aber auch so aussehen können:

$auto->setReifenReparaturObjekt($reifenKit);

Das Reifenkit-Objekt hat die selbe Schnittstelle, macht aber etwas anderes: Es hebt das Fahrzeugt mit dem Wagenheber an, damit das Rad unbelastet ist, baut einen Kompressor mit Geltank auf, schließt ihn an die Bordelektronik an, füllt den platten Reifen mit Gel, baut alles wieder ab, ab in den Kofferraum mit dem Rest und fertig.

Der Vorteil dieser Methode ist denkbar einfach: Sollte laut europäischer StVO mal eine andere Methode vorgeschrieben werden, um Reifen wieder flott zu kriegen, programmiert man das neue Objekt und tauscht das alte gegen das neue ein - vielleicht sogar zur Laufzeit.

Ein Nachteil der ganzen Dekoriererei in Verbindung mit Polymorphie ist natürlich, das zur Laufzeit alle möglichen Objekte verwendet werden können. Dann ist es etwas verzwickter, wenn man debuggen muss. Aber hey, statt einer riesen Kernel-Änderung muss vielleicht nur ein kleines Objekt ausgetauscht werden ;-)

Fazit

Ganz klar, beide Methoden haben ihre Vorteile, aber ich denke es macht erst richtig Sinn, wenn man beide Methoden miteinander kombiniert.

Teile und genieße
  • MisterWong
  • del.icio.us
  • Technorati
  • Digg
  • Slashdot
  • YahooMyWeb
  • Furl
  • Ma.gnolia
  • Spurl
  • Netscape
  • StumbleUpon
  • MyShare
  • blogmarks

Primusio meint dazu:

19. Dezember 2007 um 11:29

Meines Wissens nach war doch die Mehrfachvererbung in PHP nicht möglich oder Irre ich mich ? Gibt es evtl. einen Weg dies zu umgehen ? Oder bezog sich dein Eintrag eher auf allgemeines OOP ?

Übrigens wirklich gute Seite/Blog gefällt mir sehr, sehr informativ.

timi meint dazu:

19. Dezember 2007 um 11:54

Stimmt, noch gibts keine Mehrfachvererbung bei PHP, das war auch erst mal nur theoretisch zur Funktionsweise der Mehrfachvererbung. Die Dekoratoren sind aber auf jeden Fall unter PHP funktionsfähig…

RSS für Kommentare zu diesem Artikel · TrackBack URI

Schreib Deine Meinung