1. Einleitung
Von abstrakten Klassen können keine Objekte erzeugt werden. Sie dienen nur als eine Art Muster auf das wiederum andere Klassen aufbauen können, indem sie die abstrakte Klasse erweitern. So können Klassen mit sehr verschiedenen Methoden und Feldern auf eine gemeinsame Basisklasse mit hoher Abstraktion gebracht werden. Denkbar wäre es etwa, die Klassen '"BMW", "VW" und "Audi" von der gemeinsamen Oberklasse "Fortbewegungsmittel" ableiten zu lassen. Diese Oberklasse wäre zu abstrakt, um selbst instanziiert zu werden, könnte aber eine Methode "bewegeZu($x, $y, $z)" vorschreiben, die von allen Unterklassen implementiert werden muss.
Abstrakte Klassen dürfen abstrakte Methoden enthalten. Das sind Methoden, deren Schnittstelle (also Name und Parameter) zwar definiert sind, die aber keinen „Körper” bzw. Inhalt haben. Sie sind nur Teil der Klasse, um zu signalisieren, dass abgeleitete Klassen diese Methoden implementieren müssen. Andere Methoden oder Klassen können sich dann darauf verlassen, dass von der abstrakten Klasse abgeleitete Klassen diese Methoden auch wirklich zur Verfügung stellen. Die zuvor genannte Methode "bewegeZu($x, $y, $z)" wäre ein Beispiel dafür.
2. Beispiel: Klasse Haustier
In diesem Beispiel wird eine abstrakte Klasse „Haustier” definiert. Von dieser Klasse wiederum leiten sich die Klassen „Hauskatze”, „Schlange” und „Schwein” ab. Die Klasse „Haustier” übernimmt bereits die Handhabung des Namens des Haustiers (über Feld $name und die Methoden setName() und getName()). Die drei abgeleiteten Klassen müssen sich also nicht mehr um den Namen des Tiers kümmern. Gleichzeitig gibt „Haustier” vor, dass jede abgeleitete Klasse eine Methode „fuetterMit($essen)” implementieren muss. Da die Reaktion der Tiere auf das jeweilige $essen sehr unterschiedlich ausfallen soll — abhängig von der Tierart — macht es keinen Sinn, die Methode bereits in „Haustier” zu implementieren. Man weiß jedoch, dass jedes Tier etwas essen muss, daher wird die Methode hier vorgeschrieben.
<?php /** * Abstrakte Klasse für Haustiere. * Durch die Klasse wird die Verwaltung der Namen der Haustiere bereits übernommen. * In abgeleiteten Klassen muss das daher nicht mehr umgesetzt werden. * Die Klasse schreibt aber eine Methode zum Füttern des Haustiers vor. * Da die Reaktion darauf zwischen den Haustieren sehr unterschiedlich sein kann, * muss diese in den abgeleiteten Klassen definiert werden. */ abstract class Haustier { private $name; public function __construct($name) { $this->name = $name; } public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } // Diese Methode muss in abgeleiteten Klassen überschrieben werden abstract public function fuetterMit($essen); } // Klasse für Hauskatzen class Hauskatze extends Haustier { public function fuetterMit($essen) { // Hauskatzen mögen nur Katzenfutter oder Würstchen if ($essen==='Katzenfutter' || $essen==='Würstchen') { echo("Mmmh... mampf mampf\n"); } else { echo("Igitt!\n"); } } } // Klasse für Schlangen class Schlange extends Haustier { public function fuetterMit($essen) { // Schlangen sind wählerisch und wollen nur Mäuse als Snack haben if ($essen==='Maus') { echo("Mmmh... zzzzz... mampf mampf\n"); } else { echo("Igitt!\n"); } } } // Klasse für Schweine class Schwein extends Haustier { public function fuetterMit($essen) { // Schweine essen alles. echo("Oink oink! Mampf mampf...\n"); } } // Objekte jeder Klasse werden erzeugt $tigger = new Hauskatze('Tigger'); $mrSnake = new Schlange('MrSnake'); $schlabber = new Schwein('Schlabber'); // Die drei verschiedenen Tiere werden nacheinander gefüttert echo("Füttere Tigger mit Würstchen...\n"); $tigger->fuetterMit('Würstchen'); echo("Füttere MrSnake mit Schokolade...\n"); $mrSnake->fuetterMit('Schokolade'); echo("Füttere Schlabber mit Vollkornkeksen...\n"); $schlabber->fuetterMit('Vollkornkekse'); ?>
Füttere Tigger mit Würstchen... Mmmh... mampf mampf Füttere MrSnake mit Schokolade... Igitt! Füttere Schlabber mit Vollkornkeksen... Oink oink! Mampf mampf...