Überladung
Überladung bietet in PHP Möglichkeiten, um dynamisch
Eigenschaften und Methoden zu "erzeugen".
Diese dynamisch erzeugten Entitäten werden unter
Zuhilfenahme von magischen Methoden verarbeitet,
die man in einer Klasse zu verschiedenen Aktivitäten
definieren kann.
Die Überladungsmethoden werden aufgerufen, wenn mit
Eigenschaften oder Methoden interagiert wird, die entweder
nicht deklariert wurden oder im aktuellen Geltungsbereich
nicht sichtbar
sind. Im Rest dieses Abschnitts werden die Begriffe
"unzugreifbare Eigenschaft" und
"unzugreifbare Methode" verwendet, um auf die
Kombination von Deklaration und Sichtbarkeit zu verweisen.
Alle Überladungsmethoden müssen als public
definiert sein.
Hinweis:
Keiner der Parameter dieser magischen Methoden kann
als
Referenz übergeben werden.
Hinweis:
Die Interpretation von "Überladung" weicht
von den meisten objektorientierten Programmiersprachen
ab. Traditionell bezeichnet Überladung die Möglichkeit
mehrere Methoden mit gleichem Namen aber unterschiedlichen
Anzahlen und Typen von Parametern zu definieren.
Überladung von Eigenschaften
public void __set
(
string $name
,
mixed $value
)
public mixed __get
(
string $name
)
public bool __isset
( string $name
)
public void __unset
( string $name
)
__set wird aufgerufen, wenn Daten in unzugreifbare
Eigenschaften geschrieben werden sollen.
__get wird verwendet, um Daten aus unzugreifbaren
Eigenschaften zu lesen.
__isset wird aufgerufen, indem
isset() oder empty()
auf unzugreifbare Eigenschaften angewendet wird.
__unset wird aufgerufen, wenn
unset() für unzugreifbaren Eigenschaften
aufgerufen wird.
Der Parameter $name beinhaltet den Namen
der Eigenschaft, mit der interagiert wird. Der Parameter
$value der Funktion __set
spezifiziert den Wert den die Eigenschaft $name
annehmen soll.
Überladung von Eigenschaften funktioniert nur im Kontext von
Objekten. Diese magischen Methoden werden nicht aus einem
statischen Kontext aufgerufen. Diese Methoden sollten daher
nicht als static
deklariert werden. Seit PHP 5.3.0 wird eine Warnung ausgegeben,
wenn eine dieser magischen Überladungsmethoden als
static deklariert ist.
Hinweis:
Der Rückgabewert von __set wird, aufgrund
der Behandlung des Zuweisungsoperators in PHP, ignoriert.
Aus ähnlichen Gründen wird __get nicht
aufgerufen, wenn man Zuweisungen in etwa wie folgt verkettet:
Hinweis:
Es ist unmöglich überladene Eigenschaften in anderen Sprachkonstrukten als
isset() zu verwenden. Das heißt, falls
empty() für eine überladene Eigenschaft aufgerufen wird,
so wird die Überladungsmethode nicht aufgerufen.
Diese Einschränkung kann umgangen werden, indem die überladene Eigenschaft
in eine lokale Variable des aktuellen Gültigkeitsbereiches kopiert wird
und diese an empty() übergeben wird.
Beispiel #1
Überladung von Eigenschaften mit den Methoden
__get, __set,
__isset und __unset
<?php
class EigenschaftTest
{
/** Speicherplatz für überladene Daten. */
private $data = array();
/** Überladung wird nicht bei deklarierten Eigenschaften benutzt. */
public $declared = 1;
/** Überladung wird nur von außerhalb der Klasse angewendet. */
private $hidden = 2;
public function __set($name, $value)
{
echo "Setze '$name' auf '$value'\n";
$this->data[$name] = $value;
}
public function __get($name)
{
echo "Lese '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Undefinierte Eigenschaft für __get(): ' . $name .
' in ' . $trace[0]['file'] .
' Zeile ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
/** Seit PHP 5.1.0 */
public function __isset($name)
{
echo "Ist '$name' gesetzt?\n";
return isset($this->data[$name]);
}
/** Seit PHP 5.1.0 */
public function __unset($name)
{
echo "Lösche '$name'\n";
unset($this->data[$name]);
}
/** Keine magische Methode, nur beispielhaft hier. */
public function getHidden()
{
return $this->hidden;
}
}
echo "<pre>\n";
$obj = new EigenschaftTest;
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";
echo $obj->declared . "\n\n";
echo "Wir experimentieren nun mit der private-Eigenschaft 'hidden':\n";
echo "Private ist innerhalb der Klasse sichtbar, also wird __get() nicht benutzt...\n";
echo $obj->getHidden() . "\n";
echo "Private nicht sichtbar von außerhalb der Klasse, also wird __get() benutzt...\n";
echo $obj->hidden . "\n";
?>
Das oben gezeigte Beispiel erzeugt folgende
Ausgabe:
Setze 'a' auf '1'
Lese 'a'
1
Ist 'a' gesetzt?
bool(true)
Lösche 'a'
Ist 'a' gesetzt?
bool(false)
1
Wir experimentieren nun mit der private-Eigenschaft 'hidden':
Private ist innerhalb der Klasse sichtbar, also wird __get() nicht benutzt...
2
Private nicht sichtbar von außerhalb der Klasse, also wird __get() benutzt...
Lese 'hidden'
Notice: Undefinierte Eigenschaft für __get(): hidden in <file> Zeile 70 in <file> on line 29
Überladung von Methoden
public mixed __call
(
string $name
,
array $arguments
)
public static mixed __callStatic
(
string $name
,
array $arguments
)
__call wird aufgerufen, wenn eine unzugreifbare
Methode in einem Objekt aufgerufen wird.
__callStatic wird aufgerufen, wenn eine
unzugreifbare Methode in einem statischen Kontext aufgerufen wird.
Der Parameter $name ist der Name der aufgerufenen
Methode. Der Parameter $arguments beinhaltet ein
Array mit den Parametern, die der Methode $name
übergeben wurden.
Beispiel #2
Überladung von Methoden mit den methoden __call
und __callStatic
<?php
class MethodenTest {
public function __call($name, $arguments)
{
// Achtung: Der Wert von $name beachtet die Groß-/Kleinschreibung
echo "Rufe die Objektmethode '$name' "
. implode(', ', $arguments). "\n";
}
/** Seit PHP 5.3.0 */
public static function __callStatic($name, $arguments)
{
// Achtung: Der Wert von $name beachtet die Groß-/Kleinschreibung
echo "Rufe die statische Methode '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodenTest;
$obj->runTest('eines Objektes auf');
MethodTest::runTest('aus statischem Kontext auf'); // Seit PHP 5.3.0
?>
Das oben gezeigte Beispiel erzeugt folgende
Ausgabe:
Rufe die Objektmethode 'runTest' eines Objektes auf
Rufe die statische Methode 'runTest' aus statischem Kontext auf