Destruktoren

Als Konstruktor bezeichnet man diejenigen Methoden, die bei der Instanziierung einer Klasse aufgerufen werden. Ihr Gegenstück sind Destruktoren, die dementsprechend bei der Zerstörung eines Objekts zum Zuge kommen.

In Destruktoren können Aufgaben erledigt werden, die jedes mal noch getan werden sollen, bevor eine Instanz endgültig nicht mehr existiert. Das kann z.B. das Speichern von Session-Daten oder das Schließen einer Datenbank-Verbindung sein. Die Signatur von Destruktoren lautet in PHP:

public function __destruct();

Neben der impliziten (also automatischen) Zerstörung von Objekten kann das auch explizit beauftragt werden, indem der Referenz-Variablen null zugewiesen wird oder sprach-abhängige Methode bzw. Funktion aufgerufen wird. In PHP wird dafür unset() verwendet.

Hat in PHP ein Objekt Referenzen auf weitere Objekte, werden letztere nur dann ebenfalls vernichtet, wenn im Skript keine weiteren Referenzen auf sie existieren. An dieser Stelle sollte man im Hinterkopf behalten, dass Objekte in PHP seit Version 5 grundsätzlich by reference übergeben werden und nur durch einen Aufruf von clone tatsächlich eine Kopie erstellt wird.

Um das zu testen, kann man zwei Klassen definieren, die jeweils einen Konstruktor und einen Destruktor haben. Um die Instanzen voneinander unterscheiden zu können, erhalten sie eine eindeutige ID ($_ident).

class KlasseA
{
  private $_klasseB = null;
  private $_ident   = null;

  public function __construct(KlasseB $obj)
  {
    $this->_ident = uniqid();
    echo __METHOD__, " ", $this->_ident, "<br />";
    $this->_klasseB = $obj;
  }

  public function __destruct()
  {
    echo __METHOD__, " ", $this->_ident, "<br />";
  }
}

class KlasseB
{
  private $_ident = null;

  public function __construct()
  {
    $this->_ident = uniqid();
    echo __METHOD__, " ", $this->_ident, "<br />";
  }

  public function __destruct()
  {
    echo __METHOD__, " ", $this->_ident, "<br />";
  }

  public function __clone()
  {
    echo __METHOD__, " => Kopie von ", $this->_ident, " wurde erstellt.<br />";
    $this->_ident = uniqid();
  }
}

Anschließend können Objekte erzeugt und wieder vernichtet werden. Die Ausgaben helfen dabei festzustellen, wann welche Methoden aufgerufen werden.

$klasseB = new KlasseB();

// Die folgenden Instanzen der Klasse KlasseA erhalten beide die Referenz aus dasselbe Objekt
$klasseA1 = new KlasseA($klasseB);
$klasseA2 = new KlasseA($klasseB);
// Das Objekt in $klasseA3 erhält eine Kopie der Instanz von KlasseB
$klasseA3 = new KlasseA(clone $klasseB);

// An dieser Stelle wird die in $klasseB gespeicherte Referenz gelöscht - nicht aber das
// Objekt, weil Referenzen darauf in den Eigenschaften von $klasseA1 und $klasseA2 existieren
unset($klasseB);

echo "<br />";

echo "<b>$klasseA1 wird null zugewiesen:</b><br />";
$klasseA1 = null;
// Ergebnis: Es wird nur der Destruktor von $klasseA1 aufgerufen, da auf das Objekt von KlasseB
// noch eine weitere Referenz existiert (in $klasseA2)

echo "<b>$klasseA3 wird an unset() übergeben</b><br />";
unset($klasseA3);
// Ergebnis: Zusätzlich zum Destruktor von $klasseA3 wird auch der Destruktor KlasseB aufgerufen.
// Das passiert, weil $klasseA3 die einzige Referenz auf diese Instanz der KlasseB besitzt.

echo "<br />";

echo "<b>Ende des Skripts:</b><br />";
// An dieser Stelle werden alle noch existierenden Instanzen zerstört.

Führt man diese Code-Zeilen aus, entsteht im Browser eine Ausgabe, ähnlich der folgenden:

KlasseB::__construct 4a1e8610b60e2
KlasseA::__construct 4a1e8610b617f
KlasseA::__construct 4a1e8610b61e9
KlasseB::__clone => Kopie von 4a1e8610b60e2 wird erstellt.
KlasseA::__construct 4a1e8610b62c6

$klasseA1 wird null zugewiesen:
KlasseA::__destruct 4a1e8610b617f

$klasseA3 wird an unset() übergeben
KlasseA::__destruct 4a1e8610b62c6
KlasseB::__destruct 4a1e8610b6265

Ende des Skripts:
KlasseA::__destruct 4a1e8610b61e9
KlasseB::__destruct 4a1e8610b60e2
Annika , 03.08.2010 um 20:50

php destruct destruktor