PHP Handbuch | ||
---|---|---|
Zurück | Kapitel 14. Klassen und Objekte | Nach vorne |
Referenzen innerhalb des Konstruktors können zu verwirrenden Resultaten führen. Dieser Abschnitt hilft, Probleme zu vermeiden.
class Foo { function Foo($name) { // eine Referenz innerhalb des globalen Arrays $globalref erstellen global $globalref; $globalref[] = &$this; // setze den Namen auf den übergebenen Wert $this->setName($name); // und gib' ihn aus $this->echoName(); } function echoName() { echo "<br>",$this->name; } function setName($name) { $this->name = $name; } } |
Prüfen wir, ob zwischen $bar1, die mittels dem Operator zum Kopieren = erstellt wurde, und $bar2, die mittels dem Referenzoperator =& erstellt wurde, besteht...
$bar1 = new Foo('set in constructor'); $bar1->echoName(); $globalref[0]->echoName(); /* Ausgabe: set in constructor set in constructor set in constructor */ $bar2 =& new Foo('set in constructor'); $bar2->echoName(); $globalref[1]->echoName(); /* Ausgabe: set in constructor set in constructor set in constructor */ |
Scheinbar besteht kein Unterschied, aber tatsächlich existiert ein signifikanter: $bar1 und $globalref[0] sind NICHT referenziert, d.h. sie sind NICHT die selbe Variable. Das kommt daher, dass "new" nicht automatisch eine Referenz, sondern eine Kopie zurückgibt.
Anmerkung: Das zurückgeben von Kopien anstatt von Referenzen stellt keinen Performanceverlust dar (da PHP 4 und höher Reference Counting verwendet). Andererseits ist es sehr oft besser, einfach mit Kopien anstatt mit Referenzen zu arbeiten, da die Erstellung von Referenzen etwas Zeit in Anspruch nimmt, während das Erstellen von Kopien so gut wie keine Zeit braucht (sofern keine von ihnen ein großes Array oder Objekt ist, und eines davon geändert wird und das/die andere/n nachträglich. In diesem Fall wäre es besser, Referenzen zu verwenden, um sie alle gleichzeitig zu ändern).
// nun werden wir den Namen ändern. Was erwarten Sie? // ...dass sowohl $bar1, als auch $globalref[0] ihre Namen ändern... $bar1->setName('set from outside'); // wie bereits zuvor erwähnt, ist dies nicht der Fall $bar1->echoName(); $globalref[0]->echoName(); /* Ausgabe: set from outside set in constructor */ // lassen Sie uns den Unterschied zwischen $bar2 and $globalref[1] ansehen $bar2->setName('set from outside'); // glücklicherweise sind sie nicht nur nicht gleich, sondern auch die selbe // Variable; demnach sind $bar2->name und $globalref[1]->name ebenfalls gleich $bar2->echoName(); $globalref[1]->echoName(); /* Ausgabe: set from outside set from outside */ |
Ein anderes, letztes Beispiel zum Verständnis:
class A { function A($i) { $this->value = $i; // finden Sie heraus, warum wir hier keine Referenz benötigen $this->b = new B($this); } function createRef() { $this->c = new B($this); } function echoValue() { echo "<br>","class ",get_class($this),': ',$this->value; } } class B { function B(&$a) { $this->a = &$a; } function echoValue() { echo "<br>","class ",get_class($this),': ',$this->a->value; } } // überlegen Sie, warum hier die Verwendung einer einfachen Kopie in der // mit * markierten Zeile zu einem unerwünschten Ergebnis führen würde $a =& new A(10); $a->createRef(); $a->echoValue(); $a->b->echoValue(); $a->c->echoValue(); $a->value = 11; $a->echoValue(); $a->b->echoValue(); // * $a->c->echoValue(); /* Ausgabe: class A: 10 class B: 10 class B: 10 class A: 11 class B: 11 class B: 11 */ |
Zurück | Zum Anfang | Nach vorne |
Die "magischen" Funktionen __sleep und __wakeup | Nach oben | Referenzen in PHP |