PHP bağlayıcı geç statik aşırı mümkün mü?

3 Cevap php

Sürüm 5.3 ile başlayarak, statik yöntemler için PHP destekler late binding. Bir kuşkusuz yararlı bir özellik olsa da, kullanımı gerçekten gerekli olup, sadece birkaç vaka (örneğin Active Record desen) vardır.

Bu örnekleri göz önünde bulundurun:

1. Convenience constructors (::create())

class SimpleObject
{
    public function __construct() { /* ... */ }

    public static function create()
    {
        return new static; // or: return new self;
    }
}

Bu sınıf uzayabilir, (ancak, aynı paket içinde herhangi bir sınıf tarafından genişletilmiş değil) geç statik sadece, ::create() yöntemini yeniden yazmak zorunda kalmadan (daha kolay uzanan, ve yapmak için kullanılan bağlama gerektiğini daha da önemlisi,) bunu yapmak için hatırlamak zorunda kalmadan?

Note: this idiom is used to work around the impossibility to call methods on just constructed objects: new SimpleObject()->doStuff() PHP geçersiz.


2. Class constants

class TagMatcher
{
    const TAG_PATTERN = '/\<([a-z\-]+?)\>/i';

    private $subject;

    public function construct($subject) { $this->subject = $subject; }

    public function getAllTags()
    {
        $pattern = static::TAG_PATTERN;
        preg_match_all($pattern, $this->subject);
        return $pattern[1];
    }
}

Bu örnekte, static:: kullanımı nedeni bir öncekine benzer. Bu sınıf sadece uzanan ve sabit kılarak farklı oluşturduğu etiketleri maç yapılabilir çünkü sadece kullanılır.


Yani, tüm kadar tamamlamayı, bağlama geç statik bu kullanımları (ve benzer olanlar) bir overkill vardır? Herhangi bir fark performans bulunanlar var mı? Ayrıca, geç bağlama sık kullanımı opcode önbelleklerini tarafından verilen genel bir performans artışı azaltır mı?

3 Cevap

Yani, tüm kadar tamamlamayı, bağlama geç statik bu kullanımları (ve benzer olanlar) bir overkill vardır? Herhangi bir fark performans bulunanlar var mı? Ayrıca, geç bağlama sık kullanımı opcode önbelleklerini tarafından verilen genel bir performans artışı azaltır mı?

Geç statik bağlayıcı düzeltmeleri PHP'nin nesne modelindeki bir kusur giriş. Bu semantik hakkında, performansı hakkında değil.

Örneğin, ben yöntemi uygulanması kullanmaz zaman statik yöntemler kullanmak ister $this. Bir yöntem statik sırf bazen geçersiz istemiyorum söylemek anlamına gelmez. Önce PHP 5.3, davranış statik yöntemini overrode eğer hata bayraklı idi, ama PHP sadece devam edin ve sessizce ebeveynin sürümünü kullanmak. Örneğin, PHP 5.3 önce baskılar 'A' aşağıda kodu. Bu son derece beklenmedik bir davranış.

Geç statik bağlayıcı düzeltmeleri, ve şimdi aynı kodunu basar 'B'.

<?php
class A {
  public static function who() {
    echo __CLASS__;
  }
  public static function test() {
    self::who();
  }
}

class B extends A {
  public static function who() {
    echo __CLASS__;
  }
}

B::test();
?>

Statik yöntemler (erken veya geç-ciltli) sıkı bağlantı oluşturmak ve (böylece) edilebilirliğini azaltır. Eğer daha birkaç statik çağrıları kullanılmadan PHP büyük programlar oluşturabilirsiniz. Benim için, geç statik yöntemleri olmayan bir özelliktir.

edit Marco DeMaio sveyausunu cevaplamak için, how do static method reduce testability?

Bu, statik üyeleri (veri ve yöntemler hem de) are yararlı sizin için apaçık eğer üzgünüm ve sveyaumlulukla kullanılırsa, ben onların yaygın kötüye ima edilmiş hiçbir zarar yok.

Bir SQL veritabanı kullanan bir web uygulaması var söylüyveyalar. sizin iş nesneleri statik arabirimini veya polimveyafizm aracılığıyla kullanarak veri almak. ya da

class MyBusinessObject
extends...
{
  public function doThisOrThat(...)
  {
    $results = db::query('sql string...');
    ...
  }
}

veya

class MyBusinessObject
extends...
{
  public function __construct(dbconn $db)
  {
    $this->db = $db;
  }
  private $db;
  public function doThisOrThat(...)
  {
    $results = $this->db->query('sql string...');
    ...
  }
}

the latter is easier to test (as in: i want to test that the sql string constructed from such-and-such inputs is such-and-such) because it's easier to create another implementation of the dbconn interface than it is to change the meaning of db::. why you'd want either? because you don't need a real database to test the sql-composing behaviveya, and in fact it's easier to test fveya without a real database. also, it's easier to stub out the sql consumer if your tests are concerned with another aspect of the CUT (Code Under Test).

testing always implies lying to the tested code about its collabveyaatveyas, and abstaining from static interfaces (the "doublecolon" veya "quadridot") means the lie need not be a massive surgery, which is a plus, since the farther the tested code is from the production code, the less meaningful the test results are.

Ben kullanma ihtiyacı bulmak nerede bağlama geç statik PHPUnit ile birim test için statik yöntemler alaya sağlamaktır. Ben sorun ben alaycı izin kesinlikle kodunu değiştirmeyi sevmiyorum, ama bu üzerinde alabiliriz.

Sorunuzu yanıtlamak için, ancak, ben bu taşır neyse performans maliyet, çoğu programın çalıştırmalar karşılaştırıldığında soluk olacak bahse girerim. Diğer bir deyişle, bu bir fark yapmaz.