Der new-Operator erzeugt ein neues Exemplar einer
Klasse, ein Objekt. Als Rückgabe liefert er eine Referenz
auf dieses neue Objekt. Diese Referenz wird in einer Variablen abgelegt.
Über diese Variable kann das Objekt im Programm angesprochen werden.
Der PHP-Interpreter unterscheidet Objekte anhand einer eindeutigen ID,
die er beim Anlegen des Objektes vergibt. Um zu testen, ob zwei Variablen
dasselbe Objekt referenzieren, kann der Operator ===
verwendet werden.
Beispiel 1.8: Überprüfung der Objektidentität mit dem === Operator
<?php
class Klasse {
}
$a = new Klasse;
$b = $a;
if ($a === $b) {
print '$a und $b referenzieren dasselbe Objekt.' . "\n";
}
?>$a und $b referenzieren dasselbe Objekt.
Enthält keine Variable mehr eine Referenz auf ein Objekt, so wird es gelöscht und der belegte Speicher wird freigegeben (Garbage Collection).
Eine besondere Referenz enthält die Pseudovariable
$this. Über diese kann ein Objekt auf seine eigenen
Instanzvariablen und Methoden zugreifen. So wird in
Beispiel 1.9
die Instanzvariable $variable des Objektes gesetzt,
das durch die Variable $objekt referenziert wird.
Beispiel 1.9: Verwendung der Pseudovariablen $this
<?php
class Klasse {
private $variable;
public function setzeVariable($neuerWert) {
$this->variable = $neuerWert;
}
}
$objekt = new Klasse;
$objekt->setzeVariable('test');
?>Das Ablegen einer Referenz auf ein anderes Objekt in einer Instanzvariablen eines Objektes nennt man Aggregation. Man sagt in solch einem Fall, dass ein Objekt ein anderes aggregiert. Leitet ein Objekt einen Methodenaufruf an ein aggregiertes Objekt weiter, so spricht man von Delegation.
Manchmal möchte man anstelle einer Referenz eine Kopie eines
Objektes verwenden. Beispielsweise wenn einer Methode ein Objekt als
Parameter übergeben wird, man dieses Objekt aber nicht nach außen
sichtbar verändern möchte. Mit dem clone-Operator kann man
eine solche Kopie eines Objektes erzeugen.
Die Anwendung des clone-Operators auf ein
Objekt erzeugt eine exakte Kopie desselben und liefert eine Referenz
auf dieses neue Objekt.
Beispiel 1.10: Klonen von Objekten
<?php
class Klasse {
}
$original = new Klasse;
$kopie = clone $original;
if ($original !== $kopie) {
print '$original und $kopie referenzieren nicht ' .
"dasselbe Objekt.\n";
}
?>$original und $kopie referenzieren nicht dasselbe Objekt.
Wird keine exakte Kopie eines Objektes gewünscht, so kann der
Kopiervorgang in der entsprechenden Klasse mit einer
__clone-Methode angepasst werden. Innerhalb
dieser Methode zeigt die Pseudovariable $this
bereits auf die Kopie des Originalobjektes, die mit den
Instanzvariablen desselben initialisiert wurde.
Die Klasse Connection aus
Beispiel 1.11
kapselt neben den Zugangsdaten für eine MySQL-Serververbindung auch eine
Ressource, die eine bestehende Verbindung repräsentiert. Die definierte
__clone-Methode baut nach dem Klonen eines Objektes
der Klasse Connection eine neue Verbindung zur
Datenbank auf und benutzt hierzu die aus dem Originalobjekt kopierten
Verbindungsdaten.
Beispiel 1.11: Den Kopiervorgang eines Objektes anpassen
<?php
class Connection {
private $connection;
private $host;
private $database;
private $user;
private $pass;
public function __construct($host,$database,$user,$pass) {
$this->connect($host, $database, $user, $pass);
}
public function __clone() {
$this->connect();
}
public function
connect($host='', $database='', $user='', $pass='') {
if (!empty($host)) {
$this->host = $host;
}
if (!empty($database)) {
$this->database = $database;
}
if (!empty($user)) {
$this->user = $user;
}
if (!empty($pass)) {
$this->pass = $pass;
}
$this->connection = mysql_connect(
$this->host,
$this->user,
$this->pass,
TRUE
);
mysql_select_db($this->database, $this->connection);
}
}
?>
Das Anpassen des Kopiervorgangs mit einer __clone-Methode
ist ebenfalls notwendig, wenn das zu kopierende Objekt ein anderes
Objekt aggregiert. Ohne eine Anpassung des Kopiervorgangs würde nämlich
die entsprechende Instanzvariable der Kopie eine Referenz auf das
vom Original aggregierte Objekt enthalten (Shallow Copy).
Beispiel 1.12 zeigt
eine __clone-Methode, die eine so genannte
Deep Copy erzeugt. Hierbei wird das aggregierte
Objekt kopiert, und nicht die Referenz auf dieses.
Beispiel 1.12: Implementieren von Deep-Copy mit __clone()
<?php
class Aggregat {
}
class Klasse {
protected $aggregat;
public function __construct() {
$this->aggregat = new Aggregat;
}
public function __clone() {
$this->aggregat = clone $this->aggregat;
}
public function aggregat() {
return $this->aggregat;
}
}
$original = new Klasse;
$kopie = clone $original;
if ($original->aggregat() !== $kopie->aggregat()) {
print 'Original und Kopie aggregieren nicht dasselbe Objekt.';
}
?>Original und Kopie aggregieren nicht dasselbe Objekt.
Möchte man erreichen, dass nur Methoden des Objektes selbst dieses klonen
dürfen, so ist die __clone-Methode als
protected zu deklarieren. Soll das Klonen eines Objektes
vollständig unterbunden werden, ist die __clone-Methode
als final private zu deklarieren.