New self () ne yapar; PHP'de ne anlama geliyor?


110

Hiç böyle bir kod görmedim:

public static function getInstance()
{
    if ( ! isset(self::$_instance)) {
        self::$_instance = new self();
    }
    return self::$_instance;
}

İle aynı new className()mı?

DÜZENLE

Sınıf kalıtımsal ise, hangi sınıfa işaret ediyor?



@ stereofrog, tekil kalıbın terk edilmesi gerektiğini mi söylüyorsunuz? Ama her şeyin bir nedeni var, değil mi?
user198729

Oh, bu noktaya katılıyorum: singleton fabrika ile değiştirilmelidir
user198729

@stereofrog Singleton, birim testi için zehirlidir, durumu bir aramadan diğerine değiştiren bir şey üzerinde değişmez testler yapmak son derece zordur.
David

Maalesef bu yöntem genişlemeyecek. Size her zaman bu fonksiyonun tanımlandığı sınıftan yeni bir nesne verecektir.
Ares

Yanıtlar:


211

self yazıldığı sınıfı gösterir.

Öyleyse, getInstance yönteminiz bir sınıf adındaysa MyClass, aşağıdaki satır:

self::$_instance = new self();

Aynı şeyi yapacak:

self::$_instance = new MyClass();



Düzenleme: yorumlardan sonra birkaç bilgi daha.

Birbirini genişleten iki sınıfınız varsa, iki durumunuz vardır:

  • getInstance alt sınıfta tanımlanmıştır
  • getInstance ebeveyn sınıfta tanımlanmıştır

İlk durum şöyle görünecektir (Bu örnek için gerekli olmayan tüm kodları kaldırdım - tekli davranışı elde etmek için tekrar eklemeniz gerekecek) *:

class MyParentClass {

}
class MyChildClass extends MyParentClass {
    public static function getInstance() {
        return new self();
    }
}

$a = MyChildClass::getInstance();
var_dump($a);

Burada şunları alacaksınız:

object(MyChildClass)#1 (0) { } 

Bunun selfanlamı MyChildClass- yani yazıldığı sınıf.


İkinci durum için kod şöyle görünecektir:

class MyParentClass {
    public static function getInstance() {
        return new self();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Ve bu tür çıktılar elde edersiniz:

object(MyParentClass)#1 (0) { }

Bunun selfanlamı MyParentClass- yani burada da yazıldığı sınıf .




PHP <5.3 ile, "yazıldığı sınıf" önemlidir ve bazen sorunlara neden olabilir.

Bu nedenle PHP 5.3, staticanahtar kelime için yeni bir kullanım sunar : artık tam olarak selfbu örneklerde kullandığımız yerde kullanılabilir :

class MyParentClass {
    public static function getInstance() {
        return new static();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Ancak staticbunun yerine ile selfartık şunları alacaksınız:

object(MyChildClass)#1 (0) { } 

Bu , kullanılan sınıfastatic işaret eden bir tür anlamına gelir (MyChildClass::getInstance() , yazıldığı ) .

Elbette, selfmevcut uygulamaları bozmamak için davranışı değiştirilmedi - PHP 5.3 yeni bir davranış ekledi,static anahtar kelimeyi .


PHP 5.3 hakkında konuşurken , PHP kılavuzunun Geç Statik Bağlamalar sayfasına bir göz atmak isteyebilirsiniz .


@Paul: heu ... "kendinin takma adı gibi davranması" veya "kendi kendine işaret etme" anlamına geliyor - Fransızca "tasarımcı" fiili bunun için kullanılabilir - sanırım durumlardan biri bu aynı kelimeyi İngilizce olarak kullanmak iyi bir fikir değildir;
Pascal MARTIN

Varsa ne baseclass, classbu hangisinin işaret ediyor?
user198729

@ kullanıcı: selfKalıtım hakkında biraz daha bilgi vermek için cevabımı düzenledim ; ve ayrıca staticPHP 5.3; umarım bu yardımcı olur :-)
Pascal MARTIN

10

Bu, bir uygulaması gibi görünüyor Singleton modelinin . İşlev durağan olarak adlandırılır ve statik sınıfın değişken $_instancesetine sahip olup olmadığını kontrol eder .

Değilse, kendisinin bir örneğini başlatır ( new self()) ve içinde depolar $_instance.

Eğer ararsan className::getInstance() size alacak bir ve aynı tekil desen noktasıdır her çağrı, sınıf örneğini.

Yine de bunun böyle yapıldığını hiç görmedim ve dürüst olmak gerekirse bunun mümkün olduğunu bilmiyordum. $_instanceSınıfta ne ilan edilir?


1
$_instanceşu şekilde açıklandıpublic static $_instance;
Atif

7

Bu, büyük olasılıkla tekli tasarım modelinde kullanılır, burada kurucu, somutlaştırılmayı önlemek için özel olarak tanımlanır, çift iki nokta (::)operatörü sınıf içinde statik olarak bildirilen üyelere erişebilir, bu nedenle statik üyeler varsa, sözde değişken $ bu kullanılamaz, bu nedenle kod yerine self kullanılır, Singletons, veritabanı bağlayıcı işleyicileri gibi bir nesnenin yalnızca 1 örneğine izin veren iyi programlama uygulamalarıdır. İstemci kodundan, bu örneğe erişim, tek bir erişim noktası oluşturularak yapılacaktır, bu durumda adı ogetInstance() , getInstance kendi içinde nesneyi temelde new anahtar sözcüğünü kullanarak yapıcı yöntemi anlamına gelen bir nesne oluşturmak için oluşturan işlevdi. olarak da adlandırılır.

satır if(!isset(self::instance)), bir nesnenin önceden oluşturulmuş olup olmadığını kontrol eder, bunu anlayamazsınız, çünkü kod sadece bir parça, üstte bir yerde, muhtemelen gibi statik üyeler olmalı

private static $_instance = NULL; 

normal sınıflarda bu üyeye basitçe erişebilirdik

$this->_instance = 'something';

ancak statik olarak ilan edildi ve bu yüzden onun yerine kullandığımız $ this kodunu kullanamadık

self::$_instance

Bu statik sınıf değişkeninde depolanmış bir nesne olup olmadığını kontrol ederek, sınıf daha sonra tek bir örnek oluşturmaya veya oluşturmamaya karar verebilir, yani ayarlanmamışsa,! isset, yani statik üye $ _instance üzerinde hiçbir nesne yok demektir yeni bir nesne oluşturur $_instance, komut ile statik üyede saklanır

self::$_instance = new self();

ve müşteri koduna döndürdü. İstemci kodu daha sonra nesnenin tek bir örneğini herkese açık yöntemleriyle mutlu bir şekilde kullanabilir, ancak istemci kodunda tek erişim noktasını çağırmak, yani getInstance()yöntem de zordur, bu şekilde çağrılması gerekir

$thisObject = className::getInstance();

nedeni, işlevin kendi içinde statik olarak bildirilmesidir.


2

Evet, new className()(bu yöntemi içeren sınıfa atıfta bulunarak), muhtemelen kurucunun özel olduğu bir Singleton modelinde kullanılan gibidir.


Neden birisi PHP'de Singleton modelini kullanır? Arka plan programı benzeri bir programda kullanılmadığı sürece, singleton yalnızca komut dosyası çalışırken yaşayacak ve ardından programla birlikte kaybolacaktır.
ILikeTacos

4
rahatsız edici bir şekilde genel bir değişkene erişmek için genel beyan etmekten kaçınmak için
Sam Adamsh

0

Sınıf miras alınmışsa, çocuktan getInstance () 'i çağırmak size bir child örneği vermez. Yalnızca bir üst örnek döndürür. Bunun nedeni yeni benlik () adını vermemizdir.

Alt sınıfın bir alt sınıf örneği döndürmesini istiyorsanız, getInstance () içinde yeni static () kullanın ve ardından alt sınıf örneğini döndürür. Buna geç bağlama denir !!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.