Überladen mit PHP5

Dank einer neu eingeführten Technik steht Ihnen in PHP 5 ein Instrumentarium aus dem Werkzeugkasten der OOP zur Verfügung, das Ihre Klassen noch universeller einsetzbar macht. Ein interessantes Werkzeug aus der OOP ist das Überladen von Methoden. Hierfür müssen Sie allerdings in PHP 5 einen kleinen Umweg gehen.

Das Überladen von Methoden bedeutet, dass eine Klasse mehrere Methoden gleichen Namens besitzt. Die Unterscheidung, welche davon bei einem Aufruf tatsächlich ausgeführt wird, wird anhand der so genannten Signatur getroffen. Das ist die Konstellation aus Anzahl und der Typ der Parameter.

Existiert beispielsweise in einer Grafikanwendung eine Klasse, die den Bildschirm repräsentiert, dann verfügt sie vielleicht über mehrere Varianten der Methode zeichnen(), um ein geometrisches Element am Bildschirm anzuzeigen. Je nachdem, ob ein Kreis oder ein Polygon-Objekt dargestellt werden soll, kommt eine andere Methode zum Zug.

Nützlich ist die Verwendung dieser Technik, weil man die Schnittstellen der Objekte nach außen klar und klein hält. Es gibt eben keine spezialisierten Methoden für verschiedene geometrische Varianten, wie zeichneKreis() oder zeichnePolygon().

PHP 5 unterstützt nicht den komfortablen Weg, die Methoden mit unterschiedlicher Signatur mehrmals in die Klassendefinition aufzunehmen, wie C++ oder Java. Stattdessen wird das Überladen in PHP 5 über eine der “magischen Funktionen” realisiert. Das sind Funktionen mit vorgegebenen Namen, die man bei Bedarf in einer Klasse definiert. Sie werden immer dann aktiv, wenn keine andere Funktion explizit angesprochen wird. Für die Behandlung von undefinierten Methoden ist die Auffangfunktion __call() zuständig. Beachten Sie, dass ihr Name mit zwei Unterstrichen zu schreiben ist. Das folgende Skript zeigt das Prinzip:

<?php

class Overtest {

public function __call($m, $a){

echo "Aufgerufene Methode: $m";

}

}

$obj = new Overtest();

$obj->beispiel();

?>

Das Ergebnis des Laufes ist die Ausgabe des ermittelten Methodennamens beispiel. Der wird als erster Parameter an __call() übergeben. Der zweite Parameter enthält – in ein Array verpackt – alle Aufrufparameter der ursprünglich benutzen Methode.

Um das Überladen zu realisieren, muss man in die Funktion __class() Fallunterscheidungen einbauen. Die prüfen den übergebenen Namen sowie die Anzahl und Art der Parameter und verzweigen dann zum jeweils zuständigen Code. Sollen in einer Klasse mehrere Methoden überladen werden, ist es wegen der besseren Übersichtlichkeit ratsam, die Funktionalitäten für alle diese Varianten in private Methoden der Klasse auszulagern und __class() nur als Verteiler agieren zu lassen. Diese Funktion kann dann zwar gegebenenfalls auch sehr umfangreich werden, besitzt aber eine so klare Struktur, dass man sich darin schnell zurechtfindet.

Ein Grundgerüst für das eingangs geschilderte Beispiel einer Klasse für die Darstellung geometrischer Objekte könnte dann so aussehen:

<?php

class Geo {

public function __call($m, $a) {

if ($m=='zeichne'){

if (get_class($a[0]) == 'Kreis'){

$this->zeichneKreis($a[0]);

}

elseif (get_class($a[0]) == 'Poly'){

$this->zeichnePolyg($a[0]);

}

else {

echo "Geo::zeichne() kennt keine";

echo " Methode für die Parameter";

var_dump($a);

}

}

elseif ($m=='verschiebe') {

// ...

}

else {

echo "Geo::$m() existiert nicht";

}

}

private function zeichneKreis($objKreis) {

// ...

}

private function zeichnePoly($objPoly) {

// ...

}

}

class Kreis {

// ...

}

?>

Integrieren Sie diese Klassendefinition in ein PHP-Programm. Dann führen beispielsweise folgende Zeilen, die die Klasse nutzen, zur Meldung, dass die Methode radiere nicht vorhanden ist:

$objGeo = new Geo();

$objGeo->radiere();

Rufen Sie dagegen die Methode zeichne auf und verwenden einen nicht vorgesehenen Parameter, dann erscheint die Fehlermeldung Geo::zeichne() kennt keine Methode für… Im Beispielskript wird an diese Meldung gleich noch eine Auflistung der zum Aufruf der ursprünglichen Funktion verwendeten Parameter geliefert, um den Fehler besser analysieren zu können. Weil diese Parameter in einem Array vorliegen, verwendet das Skript dazu die PHP-Funktion var_dump().

Nur, wenn Methodenname und Signatur zueinander passen, dann wird eine der vorgesehenen internen Methoden der Geo-Klasse aufgerufen. Die folgenden Codezeilen führen beispielsweise zu einem Aufruf der Methode zeichneKreis():

$objGeo = new Geo();

$objKreis = new Kreis();

$objGeo->zeichne($objKreis);

Überladen von Instanzvariablen

Das Konzept der Überladung bietet PHP 5 auch für Instanzvariablen. Sie können damit dem Benutzer Ihrer Klassen die Existenz von Instanzvariablen vorgaukeln. Ähnlich wie __call() existieren dafür vordefinierte Funktionen, die automatisch aufgerufen werden, sobald der Zugriff auf eine unbekannte Instanzvariable erfolgt.

Da die Fälle des lesenden und schreibenden Zugriffs unterschieden werden, gibt es mit __set() und __get() zwei Spezialfunktionen für das Überladen von Instanzvariablen. Erfolgt beispielsweise das Setzen einer nicht existierenden Instanzvariable, dann ruft das PHP-System die Funktion __set() mit dem verwendeten Namen als ersten und dem gesetzten Wert als zweiten Parameter auf.

Die Funktion __set() kann daraufhin die notwendigen Schritte einleiten oder – wenn der verwendete Variablenname keine erlaubte Objekteigenschaft sein soll – eine Fehlermeldung ausgeben. Wie bei __class() müssen Sie die Unterscheidung, welche Pseudovariable gemeint ist, innerhalb der Funktionen __set() und __get() treffen. Der Vorteil liegt darin, dass Sie Validierungen vor den Zugriff schalten können, während Instanzvariablen vom Typ public von außen beliebig änderbar sind.

Ähnliche Beiträge