Yeni benliğe karşı yeni statik


513

PHP 5.2 üzerinde çalışmak için bir PHP 5.3 kitaplığı dönüştürüyorum. Yolumda duran ana şey, geç statik bağlamanın kullanılmasıdır return new static($options);, eğer bunu dönüştürürsem return new self($options)aynı sonuçları alır mıyım?

Arasındaki fark nedir new selfve new static?

Yanıtlar:


890

aynı sonuçları alacak mıyım?

Pek sayılmaz. Gerçi PHP 5.2 için bir çözüm bilmiyorum.

Arasındaki fark nedir new selfve new static?

selfnewanahtar kelimenin gerçekte yazıldığı sınıfa karşılık gelir .

staticPHP 5.3'ün geç statik bağlamaları için, hiyerarşide yöntem olarak adlandırdığınız herhangi bir sınıfı ifade eder.

Aşağıdaki örnekte, Bher iki yöntemi de miras alır A. selfÇağırma bağlı Ao 'de tanımlandığı çünkü Aise, birinci yöntemin bireyin uygulanması staticadlandırılan sınıfa bağlı olduğu (bakınız ayrıca get_called_class()).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A

mantıklı. En iyi bahis geç statik bağlama kullanan işlev sınıf adı geçmek ve sonra yeni $ className ($ options) döndürmek olduğunu düşünüyorum;
Mike

12
Sınıf adını "geçmeniz" gerekmez get_called_class(), her zaman yapabilirsiniz , ki bu etkili bir şekilde aynıdır __CLASS__, ancak LSB uyumludur.
shadowhand

7
get_called_class <PHP5.3 sürümünde mevcut değil. Bu nedenle, PHP5.2'de somut nesnenin sınıf adını almak istiyorsanız, PHP 5.3'ten PHP 5.2'ye bir kitaplığı dönüştürmeye çalışırken bu işlev yardımcı olmaz
txwikinger 21:11

2
Self :: theFunction () olarak adlandırılan işlev "Fiziksel olarak ait olduğum sınıfın bağlamında yürüteceğim" gibi davranır. static :: theFunction () olarak adlandırılan işlev "Aslında dış dünya tarafından çağrılan sınıf bağlamında yürütüleceğim" gibi davranır. (Kalıtım senaryosunu varsayarsak). Teşekkürler
Shubhranshu

2
Kafamda, sezgisel olanı alıyorum ve tersini yapıyorum. İsimlendirmeye dayanarak selfkendi kendine döneceğini ve staticgeçersiz kılınamayacak bir şeyi döndüreceğini düşünürdünüz ... Ama işte tam tersi. PHP'nin isimlendirilmesinden, konvansiyonlarından ve genel tarzından etkilenmeyi hiç bırakmam. -_-
ahnbizcad

23

Bu kodun yöntemi statik değilse, kullanarak 5.2'de bir geçici çözüm alabilirsiniz get_class($this).

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

Sonuçlar:

string(1) "B"
string(1) "B"

17
Yöntem statik değilse, geç statik bağlamalar tamamen önemsiz hale gelir.
BoltClock

1
Örneğin, nesneyi kullanmadan kopyalandığı clone, ancak yalnızca özellikleri yeniden oluşturup ayarlayarak "kopyala" yönteminde kullanabilirsiniz . $copy = new static(); $copy->set($this->get()); return $copy;
Marius Balčytis

9
@BoltClock Kesinlikle hayır? Bir alt sınıfın örnek yönteminden geçersiz kılınmış bir statik yöntem çağırıyorsanız , temel sınıfın veya alt sınıfın bu statik yöntemin sürümünün kullanılıp kullanılmayacağını seçme self::veya static::etkileme. Nedense yokluğunda arasındaki seçim, doğal olarak meydana gelen böyle bir durum kötü uygulama gösterir düşünmek (ve bu yüzden olmalı neden herhangi bir neden görmüyorum) self::ve static::bunun içinde olduğu gibi statik olmayan yöntemler içinde tıpkı alakalı statik yöntemler. Yorumunuzu yanlış anladım mı yoksa bizden biri yanlış mı?
Mark Amery

4
@ Mark Amery: Hmm ben bunu düşünmedim. Kesinlikle haklısın. Söz konusu örnek yönteminde hiçbir statik yöntemin çağrılmayacağını varsaymıştım, ancak örneğinize dayanarak, bunun nasıl naif bir varsayım olacağını görebiliyorum.
BoltClock


7

Başkalarının cevaplarına ek olarak:

static :: çalışma zamanı bilgileri kullanılarak hesaplanır.

Bu, static::özellik değerleri nedeniyle bir sınıf özelliğinde kullanamayacağınız anlamına gelir :

Derleme zamanında değerlendirilebilmelidir ve çalışma zamanı bilgisine bağlı olmamalıdır.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

kullanma self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

Yaptığım koddaki Önemli hata yorumunun hatanın nerede olduğunu göstermediğini, nesnenin yorumlarda belirtildiği gibi @Grapestain olarak başlatılmasından önce hatanın daha önce meydana geldiğini lütfen unutmayın.


4
Hatanın, public $name = static::class;örnekte önerildiği gibi, 7. hatta değil 2. hatta atıldığını unutmayın . Hata der ki: "static :: class, derleme zamanı sınıf adı çözümlemesi için kullanılamaz"; bu, sorunun $ name alanına erişmeye çalıştığınız yerde değil, çok daha önce PHP sınıfının derlenmesinde olduğunu gösterir. İlk örnekte 7. satıra (veya 6) ulaşılamaz.
sbnc.eu

@Grapestain Örnekte yaptığım yorum, nihai sonucu göstermek ve hatanın gerçekte nerede olduğunu belirtmemekti. Ama yine de bunu belirttiğin için teşekkürler.
Yağmur

Doğru, eleştirmek istemedim, başkalarına yardımcı olabileceği umuduyla beni neyin karıştırdığını netleştirdim. Yine de faydalı bir örnek!
sbnc.eu
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.