PHP Velho Oeste 2024

Kurucuların içinde Gönderimler

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.

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).

Yukarıda yazılanları bir örnekle pekiştirelim:
<?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 {
    function 
A($i) {
        
$this->değer $i;
        
// neden bir gönderime ihtiyacımız olmadığını gösterelim
        
$this->= new B($this);
    }

    function 
createRef() {
        
$this->= new B($this);
    }

    function 
değerGöster() {
        echo 
"<br />",get_class($this),' sınıfı: ',$this->değer;
    }
}


class 
{
    function 
B(&$a) {
        
$this->= &$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

add a note add a note

User Contributed Notes

There are no user contributed notes for this page.
To Top