Gönderimlerin kurucular içinde kullanımı beklenmedik sonuçlar doğurabilir. Bu öğretici tarzı bölümde bu sorunlardan nasıl kaçınabileceğinizden bahsedilecektir.
<?php
class Foo {
function Foo($isim) {
// $küreselatıf küresel dizisi içinde bir gönderim oluşturalım
global $küreselatıf;
$küreselatıf[] = &$this;
// aktarılan değere ismi atayalım
$this->isimAta($isim);
// ve çıktılayalım
$this->isimGöster();
}
function isimGöster() {
echo "<br />", $this->isim;
}
function isimAta($isim) {
$this->isim = $isim;
}
}
?>
= işleci kullanılarak bir kopya olarak oluşturulan $bar1 ile =& işleci kullanılarak gönderimli oluşturulan $bar2 arasındaki farklara bakalım...
<?php
$bar1 = new Foo('kurucu içinde atandı');
$bar1->isimGöster();
$küreselatıf[0]->isimGöster();
/* çıktısı:
kurucu içinde atandı
kurucu içinde atandı
kurucu içinde atandı */
$bar2 =& new Foo('kurucu içinde atandı');
$bar2->isimGöster();
$küreselatıf[1]->isimGöster();
/* çıktısı:
kurucu içinde atandı
kurucu içinde atandı
kurucu içinde atandı */
?>
Görünürde bir fark yok gibi ama aslında çok önemli bir fark var:
$bar1 ve $küreselatıf[0]
gönderimli olmadıkları gibi aynı değişkenler de değiller. Bunun sebebi
new
işleminin öntanımlı olarak bir gönderim değil bir kopya
döndürmesidir.
Yukarıda yazılanları bir örnekle pekiştirelim:Bilginize: Gönderim yerine kopya döndürmekle bir başarım kaybı ortaya çıkmaz (PHP 4'ten beri). Aksine, gönderim yerine kopyayla çalışmak çoğunlukla daha bile iyidir, bunun sebebi gönderim oluşturmak için harcanan zamana karşın kopya oluşturma işleminin sanal olarak hiç vakit almayışıdır (büyük bir nesne veya dizi içermemesi ve bunların ardışık olarak birbirlerini değiştirmemesi şartıyla, aksi takdirde gönderim kullanmak daha akıllıca olur).
<?php
// ismi değiştirip ne olacağını görelim
// $bar1 ve $küreselatıf[0]'ın isimlerinin değişeceğini beklersiniz...
$bar1->isimAta('dışardan atandı');
// evvelce bahsedildiği gibi bir kayıp yok
$bar1->isimGöster();
$küreselatıf[0]->isimGöster();
/* çıktısı:
dışardan atandı
kurucu içinde atandı */
// şimdi $bar2 ile $küreselatıf[1] arasındaki farkı görelim
$bar2->isimAta('dışardan atandı');
// şansa bakın ki, sadece eşit değil aynı zamanda $bar2->isim
// ve $küreselatıf[1]->isim aynılar.
$bar2->isimGöster();
$küreselatıf[1]->isimGöster();
/* çıktısı:
dışardan atandı
dışardan atandı */
?>
Son bir örnekle daha iyi anlamaya çalışalım:
<?php
class A {
function A($i) {
$this->değer = $i;
// neden bir gönderime ihtiyacımız olmadığını gösterelim
$this->b = new B($this);
}
function createRef() {
$this->c = new B($this);
}
function değerGöster() {
echo "<br />",get_class($this),' sınıfı: ',$this->değer;
}
}
class B {
function B(&$a) {
$this->a = &$a;
}
function değerGöster() {
echo "<br />",get_class($this),' sınıfı: ',$this->a->değer;
}
}
// * imli satırda istenmeyen bir sonuca yol açan basit kopya
// kullanma sebebimizi anlamaya çalışalım
$a =& new A(10);
$a->createRef();
$a->değerGöster();
$a->b->değerGöster();
$a->c->değerGöster();
$a->değer = 11;
$a->değerGöster();
$a->b->değerGöster(); // *
$a->c->değerGöster();
?>
Yukarıdaki örneğin çıktısı:
A sınıfı: 10 B sınıfı: 10 B sınıfı: 10 A sınıfı: 11 B sınıfı: 11 B sınıfı: 11