Vererbung erlaubt es, bestehenden Code zu erweitern, ohne ihn ändern
oder duplizieren zu müssen. PHP unterstützt hierbei die
klassenbasierte Einfachvererbung, bei der eine so genannte
Kindklasse sämtliche als public
und protected deklarierten Instanzvariablen und
Methoden von ihrer Elternklasse übernimmt (erbt)
[4]
. Die Kindklasse kann diese überschreiben sowie neue Instanzvariablen
und Methoden definieren.
Die Vererbungsbeziehung einer Kindklasse zu ihrer Elternklasse wird
durch das extends-Schlüsselwort in der Klassendeklaration
ausgedrückt. Eine Klasse hat in PHP maximal eine Elternklasse, sie kann
jedoch beliebig viele Kindklassen besitzen.
Mit dem Schlüsselwort final markierte Methoden der
Elternklasse können in der Kindklasse nicht redefiniert werden, als
final markierte Klassen können per Vererbung nicht
erweitert werden.
Betrachten wir als Beispiel die Erweiterung der Klasse
DB_MySQL um die Serverkonfiguration für ein
spezielles Projekt. Hierzu müssen wir lediglich eine Klasse
MyProject_DB als Kindklasse von
DB_MySQL einführen, deren Konstruktor wir dann
entsprechend redefinieren.
Abbildung 1.2
zeigt ein entsprechendes UML-Klassendiagramm. Der Pfeil symbolisiert
die Vererbung, die Kindklasse zeigt auf ihre Elternklasse.
Beispiel 1.18: Für ein Projekt spezialisierte, von DB_MySQL abgeleitete Klasse
<?php
require_once 'DB_MySQL.php';
class MyProject_DB extends DB_MySQL {
const DB_HOST = 'localhost';
const DB_DATABASE = 'test';
const DB_USER = 'root';
const DB_PASS = '';
public function __construct($query = '') {
$this->connect(
self::DB_HOST,
self::DB_DATABASE,
self::DB_USER,
self::DB_PASS
);
if (!empty($query)) {
$this->query($query);
}
}
}
?>
Durch die Möglichkeit, dem Konstruktor von MyProject_DB
eine SQL-Anfrage zu übergeben, reduziert sich der vom Verwender der Klasse
zu schreibende Code auf ein Minimum.
Beispiel 1.19 zeigt, wie
die abgeleitete Klasse den wiederkehrenden Code für SQL-Anfragen und die
Verarbeitung ihrer Ergebniszeilen auf ein Minimum reduziert. Und sollten
sich die Zugangsdaten für den MySQL-Server ändern, so müssen diese nur an
einer Stelle aktualisiert werden. Dies erhöht zusätzlich die Wartbarkeit des
Codes.
Beispiel 1.19: Verwendung der abgeleiteten Klasse
<?php
require_once 'MyProject_DB.php';
$db = new MyProject_DB('SELECT spalte FROM tabelle');
while ($row = $db->fetchRow()) {
// ...
}
?>
Wird in einer abgeleiteten Klasse keine Konstruktor- beziehungsweise
Destruktor-Methode deklariert, so wird implizit die entsprechende
Methode der Elternklasse aufgerufen. Andernfalls wird die Methode der
Kindklasse aufgerufen, ohne dass die entsprechende Methode der
Elternklasse implizit aufgerufen wird. Diese kann bei Bedarf jedoch
explizit über parent::__construct() beziehungsweise
parent::__destruct() aufgerufen werden.
Beispiel 1.20: Verhalten von Konstruktor- und Destruktormethode in abgeleiteten Klassen
<?php
class Elternklasse {
public function __construct() {
print "Elternklasse::__construct() aufgerufen.\n";
}
public function __destruct() {
print "Elternklasse::__destruct() aufgerufen.\n";
}
}
class Kindklasse extends Elternklasse {
public function __construct() {
parent::__construct();
print "Kindklasse::__construct() aufgerufen.\n";
}
}
$objekt = new Kindklasse;
?>Elternklasse::__construct() aufgerufen. Kindklasse::__construct() aufgerufen. Elternklasse::__destruct() aufgerufen.
[4] Man sagt auch, dass die Kindklasse von der Elternklasse abgeleitet wird und nennt die Kindklasse auch abgeleitete Klasse.