In den bisherigen Beispiel-Klassen wurden alle Methoden mit einem Bezeichner deklariert und definiert.
Doch es geht auch mit Konstruktoren. Bei einem Konstruktor handelt es sich um eine Magische Methode, die beim Erzeugen und
Instanziieren eines neuen Objektes automatisch mit der Klasse aufgerufen wird. Beachtenswert dabei ist, dass Konstruktormethoden
keinen funktionstypischen Rückgabewert liefern.
Zum leichteren Verständnis nachfolgend einige Beispiele als kleine Gegenüber-stellung, einmal mit definierten Methoden und
einmal mit Konstruktoren.
Erstes Beispiel mit einer definierten Methode (klasse-08a.php):
<?php class ErsteTestKlasse { private $rueckgabe = "Schuster"; public function testeMethode() { $this->rueckgabe = "Ergebnis für ".$this->rueckgabe; return $this->rueckgabe; } } $obj = new ErsteTestKlasse(); echo $obj->testeMethode()."n"; // Ausgabe: Ergebnis für Schuster
Wie aus dem ersten Beispiel ersichtlich wird, so wird beim Aufruf der ersten Test-Klasse innerhalb der
Methode ein Wert mit dem Sprachkonstrukt return zurückgegeben. Nach der Erzeugung eines Objektes kann die Ausgabe über einen
Aufruf der Methode erfolgen.
Zweites Beispiel mit einer Konstruktormethode (klasse-08b.php):
?> <?php class ZweiteTestKlasse { public $rueckgabe = "Bäcker"; public function __construct() { $this->rueckgabe = "Ergebnis für ".$this->rueckgabe; } } $obj = new ZweiteTestKlasse(); echo $obj->rueckgabe."n"; // Ausgabe: Ergebnis für Bäcker ?>
Etwas anders sieht es im zweiten Beispiel bei Verwendung einer Konstruktormethode aus. Das
Sprachkonstrukt return würde hier versagen und ein Bezeichner für eine Methode fehlt, der nach der Erzeugung eines Objektes
ansprechbar wäre. Nach Erzeugung des Objektes kann jedoch auf die öffentlichen Eigenschaften zugegriffen werden.
Drittes Beispiel mit __construct() und __toString() (klasse-08c.php):
?> <?php class DritteTestKlasse { public $rueckgabe = "Fleischer"; public function __construct() { $this->rueckgabe = "Ergebnis für ".$this->rueckgabe; } public function __toString() { return $this->rueckgabe; } } $obj = new DritteTestKlasse(); echo $obj."n"; // Ausgabe: Ergebnis für Fleischer ?>
Eine weitere Möglichkeit einen Wert für die Ausgabe zu erhalten, besteht in der Verwendung der
Magischen Methode __toString. Diese Magische Methode wird im Zusammenhang mit echo oder print versuchen ein Objekt in einen
String umzuwandeln und auszugeben.
Nachfolgend zwei weitere Beispiele in der Gegenüberstellung. Beide Exempel könnten so oder ähnlich als Grundlage für ein
Login-Script dienen.
Viertes Beispiel - Login-Script mit einer definierten Methode (klasse-08d.php):
<?php class Einwahl { private $user = "Admin"; private $pass = "EsPasst"; public function vergleicheDaten($benutzer, $passwort) { if ($benutzer == $this->user and $passwort == $this->pass) { /*------------------------------------------------------- Hier den Code für eine Verbindung zur DB bzw. für den Einwahlvorgang einfügen. Danach eine Mitteilung als Bestätigung generieren oder eine Fehlermeldung retour. -------------------------------------------------------- */ return "Einwahl war erfolgreich!n"; } else { return "Einwahl ist fehlgeschlagen!n"; } } } $ausgabe = new Einwahl(); echo $ausgabe->vergleicheDaten("Admin","EsPasst"); ?>
Das vierte Exempel unterscheidet sich nicht wesentlich vom ersten Code-Listing auf dieser Seite, mit dem
Unterschied, dass beim Erstellen des Objektes zwei Werte mit an die Methode der Klasse übergeben werden. Innerhalb der Methode
werden diese Werte mit Hilfe eines if-Statements mit den Werten der Eigenschaften auf Gleichheit überprüft. Sollte das
if-Statement true liefern, so könnte als nächster Schritt eine Verbindung zur Datenbank erstellt werden oder das Script
könnte Zugang zu einem geschützten Bereich gewähren.
Fünftes Beispiel - Login-Script mit __construct (klasse-08e.php):
<?php session_start(); class Anmeldung { private $user = "Admin"; private $pass = "EsPasst"; public $rueckgabe; public function __construct($benutzer, $passwort) { if ($benutzer == $this->user and $passwort == $this->pass) { /*------------------------------------------------------- Hier wieder den Code für eine Verbindung usw. einfügen. -------------------------------------------------------- */ $this->rueckgabe = "Anmeldung war erfolgreich!n"; } else { $this->rueckgabe = "Anmeldung ist fehlgeschlagen!n"; } } public function __destruct() { $_SESSION["speichern"] = "Die letzte ".$this->rueckgabe; } } $ausgabe = new Anmeldung("Admin","EsPasst"); echo $ausgabe->rueckgabe; ?>
Wie bei den ersten Beispielen, so wurde auch in diesem Beispiel die mit einem Bezeichner definierte
Methode gegen eine Konstruktormethode ausgewechselt. Als Ergänzung wurde zusätzlich noch eine weitere Magische Methode
verwendet, eine Destruktormethode, die zum Ende der Laufzeit des Scripts noch eine Aktion ausführen soll. Im Beispiel soll in
einer Session-Variablen gespeichert werden, ob das letzte Log-in fehlschlug oder nicht.
Wie bereits erwähnt, so handelt es sich bei der Destruktormethode um eine weitere Magische Methode, die
PHP zu bieten hat. Die Verwendung von Destruktoren ist jedoch selten erforderlich, eigentlich nur in speziellen
Ausnahmefällen.
Im Unterschied zu einer Programmiersprache wie C, muss ein Programmierer, gleich ob Einsteiger oder nicht, sich kaum darüber
Gedanken machen, ob PHP hinter ihm aufräumt und beim Aufräumen durch das Script belegten Speicher wieder frei gibt oder nicht.
Zumindest solange nicht, wie ein Script beim Verbrauch von Speicherplatz nicht die Grenzwerte des Memory Limits erreicht.
PHP verwaltet den erforderlichen Speicherbedarf eigenständig und wird am Ende eines Scripts nicht mehr benötigten
Speicherplatz für andere Anwendungen freigeben und dabei alle Objekte, Variablen und Referenzen löschen. Doch welche Aufgaben
bleiben nun eigentlich für den Destruktor übrig?
Ein Destruktor wird zum Ende eines Scripts aufgerufen oder wenn keine weiteren Referenzen auf ein Objekt mehr existieren.
Letzteres sollte dann der Fall sein, wenn die Referenzen zur Laufzeit eines Scripts durch die Zuweisung der Konstanten NULL
überschrieben oder mit unset() gelöscht werden. Wurden die Referenzen gelöscht, wird PHP den Destruktor bereits vor dem Ende
der Laufzeit eines Scripts aufrufen.
Wer testen möchte, wann wie viel Speicherplatz vom Script belegt ist, kann das nachfolgende Code-Listing erweitern und die
Funktion memory_get_usage() verwenden. Wird memory_get_usage() in den Zeilen vor und nach einer Zuweisung von NULL oder vor oder
nach dem Gebrauch von unset() eingefügt, sollte sich ein Unterschied ergeben. Zumindest in allen bisherigen Tests verhielt es
sich so.
Sechtes Beispiel mit Destruktor (klasse-08g.php):
<?php class Speicherplatz { public $rueckgabe; public function __construct($eingabe) { $this->rueckgabe = $eingabe.memory_get_usage(); } public function __destruct() { echo "Destructor<br>n"; } } /*------------------------------------------------------------------- Für Testausgaben lassen sich Aktionen mit __destruct() mehrfach vor dem Ende der Scriptlaufzeit ausführen. -------------------------------------------------------------------- */ $eingabe = new Speicherplatz("Von PHP belegter Speicherplatz in Bytes: "); echo $eingabe->rueckgabe."<br>n"; $eingabe = NULL; $eingabe = new Speicherplatz("Von PHP belegter Speicherplatz in Bytes: "); echo $eingabe->rueckgabe."<br>n"; unset($eingabe); /* Ausgabe: Von PHP belegter Speicherplatz in Bytes: 323912 Destructor Von PHP belegter Speicherplatz in Bytes: 324000 Destructor */ ?>
Nachfolgend eine erweiterte Ausgabe als Test, aus dem sich der Unterschied vor und nach dem Löschen mit
unset() ableiten lässt. Auch ist dem vorausgehenden wie dem unteren Beispiel zu entnehmen, dass der Destruktor nach jedem
Löschen aufgerufen wird.
Was ebenfalls erkennbar wird, durch das Löschen mit unset() verringert sich der verwendete Speicherplatz etwa im gleichen
Verhältnis und das unabhängig davon, ob der Destruktor auskommentiert wurde oder nicht. Letzteres liegt daran, dass allein
durch den Aufruf des Destruktors keine bereits instanziierten Objekte nachträglich zerstört werden und nur durch die
Verwendung von unset($eingabe) die Variable $eingabe einschließlich einer enthaltenen Referenz oder eines sonstigen Wertes aus
dem Speicher entfernt wird. Erst deren Entfernung aus dem Speicher führt zu einem Aufruf des Destruktors.
Wie bereits erwähnt, wurden die Test mit und ohne Destruktor durchgeführt, wobei die jeweils ermittelten Endwerte nach dem
Löschen von $eingabe mit unset stets den Anfangswerten vor der Erzeugung und Instanziierung eines Objektes entsprachen.
Siebentes Beispiel als Detail-Listing (klasse-08h.php):
<?php // ... // Eine erweiterte Ausgabe als Test echo memory_get_usage() ."<br>n"; $eingabe = new Testausgaben("Von PHP belegter Speicherplatz in Bytes: "); echo $eingabe->rueckgabe."<br>n"; echo memory_get_usage() ."<br>n"; unset($eingabe); echo memory_get_usage() ."<br>n"; echo "<br>nEine beliebige andere Ausgabe nur zur Kontrolle.<br><br>n"; echo memory_get_usage() ."<br>n"; $eingabe = new Testausgaben("Von PHP belegter Speicherplatz in Bytes: "); echo $eingabe->rueckgabe."<br>n"; echo memory_get_usage() ."<br>n"; unset($eingabe); echo memory_get_usage() ."<br>n"; /* Ausgabe: 330312 Von PHP belegter Speicherplatz in Bytes: 330600 330656 Destructor 330312 Eine beliebige andere Ausgabe nur zur Kontrolle. 330312 Von PHP belegter Speicherplatz in Bytes: 330600 330656 Destructor 330312 */ ?>
Die Verwendung eines Destruktors wird gelegentlich missverstanden. Ein Destruktor (zumindest
bei PHP) ist weniger dafür gedacht nicht mehr benötigte Ressourcen freizugeben, als vielmehr eine letzte Aktion
auszuführen.
Die Stärken eines Destruktors, die für dessen gelegentliche Verwendung sprechen, ergeben sich aus dem Umstand, dass dieser
immer aufgerufen wird wenn ein Objekt bzw. die letzte Variable, die eine Referenz auf ein Objekt enthält, gelöscht wird.
Dadurch lässt sich mit Hilfe des Destruktors vor dem endgültigen Löschen eines Objektes noch der innerhalb des Destruktors
notierte Code ausführen, falls eine Ausgabe oder abschließende Aktion stets erforderlich sein sollte. Im fünften Beispiel
wurde noch ein Wert in einer Session-Variablen gespeichert, doch es könnten auch persistente Verbindungen geschlossen oder ein
abschließender Hinweis ausgegeben werden.
Wie bereits bei beim Konstruktor erwähnt, so liefert auch der Destruktor keinen Rückgabewert im üblichen Sinne. Eine Ausgabe
kann jedoch mit echo oder print erfolgen, ebenfalls wird Code mit Anweisungen noch ausgeführt. Bei der Vererbung sind einige
Punkte zu beachten, doch dazu auf der nächsten Seite mehr.
weiterlesen » Vererbung bei Konstruktoren und D...
Einstieg in PHP
Übersicht
Diverse Themen