2009-11-29 9 views
13

Ab Version 5.3 unterstützt PHP late binding für statische Methoden. Obwohl es ein zweifellos nützliches Merkmal ist, gibt es nur einige Fälle, in denen seine Verwendung wirklich notwendig ist (z. B. das Active Record-Muster).Kann die späte statische Bindung in PHP überstrapaziert werden?

Betrachten Sie diese Beispiele:

1. Convenience Bauer (::create())

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

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

Wenn diese Klasse erweitert werden kann (es jedoch von jeder Klasse im gleichen Paket nicht verlängert wird), sollte späte statische Bindung verwendet werden, um es einfach zu erweitern (ohne die ::create() Methode neu schreiben zu müssen, und, was noch wichtiger ist, ohne sich daran erinnern zu müssen)?

Hinweis: Dieses Idiom wird verwendet, um die Unmöglichkeit zu umgehen, Methoden nur auf konstruierten Objekten aufzurufen: new SimpleObject()->doStuff() ist in PHP ungültig.


2. Klasse Konstanten

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]; 
    } 
} 

Der Grund static:: in diesem Beispiel zu verwenden, um ähnlich der vorhergehenden ist. Es wird nur verwendet, weil diese Klasse dazu verwendet werden kann, unterschiedlich geformte Tags zu vergleichen, indem sie einfach erweitert und die Konstante überschrieben wird.

Also, um alles zu verpacken, sind diese Anwendungen (und ähnliche) der späten statischen Bindung ein Overkill? Gibt es einen spürbaren Leistungseinbruch? Verringert die häufige Verwendung der späten Bindung auch die durch Opcode-Caches gegebene Gesamtleistungssteigerung?

+0

Nun, die zweite könnte erreicht werden, indem man eine private Variable außer Kraft setzt und '$ this' verwendet, oder? Oder verstehe ich etwas falsch? – Franz

+1

Ja, aber ich konnte einfach nicht zu einem besseren Beispiel kommen ... Es als "const" zu haben bedeutet, es nicht durch alle Instanzen zu kopieren. Und selbst wenn das Copy-on-Write von PHP dies optimieren würde, sieht es sicherlich als Klassenkonstante besser aus, da es sich tatsächlich um einen konstanten Wert in der gesamten Klasse handelt. –

+0

... und eigentlich meinte ich, dass in diesem Fall die Verwendung von Instanzvariablen wie ein Workaround aussieht, während 'static ::' nicht funktioniert. –

Antwort

13

Also, um alles zusammenzufassen, sind diese Anwendungen (und ähnliche) der späten statischen Bindung ein Overkill? Gibt es einen spürbaren Leistungseinbruch? Verringert die häufige Verwendung der späten Bindung auch die durch Opcode-Caches gegebene Gesamtleistungssteigerung?

Die Einführung der späten statischen Bindung behebt einen Fehler im PHP-Objektmodell. Es geht nicht um Leistung, es geht um Semantik.

Zum Beispiel verwende ich gerne statische Methoden, wenn die Implementierung der Methode $this nicht verwendet. Nur weil eine Methode statisch ist, heißt das nicht, dass Sie sie manchmal nicht überschreiben wollen. Vor PHP 5.3 war das Verhalten, dass kein Fehler markiert wurde, wenn Sie eine statische Methode übertrafen, aber PHP würde einfach weitermachen und stillschweigend die Version des Elternteils verwenden. Zum Beispiel gibt der folgende Code 'A' vor PHP 5.3 aus. Das ist höchst unerwartetes Verhalten.

Späte statische Bindung behebt es, und jetzt der gleiche Code druckt "B".

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

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

B::test(); 
?> 
+0

Bitte nach dem Kommentar kommentieren. – erenon

+11

Ich weiß, das ist ein alter Thread, aber ich habe es über Google gefunden. Ihr Beispielcode sollte eigentlich "A" unabhängig von der PHP-Version drucken. Verwenden Sie das statische Schlüsselwort, um späte statische Bindungen zu aktivieren. Z.B.ersetze self :: who(); mit static :: who(); und es sollte "B" drucken – Maurice

3

statische Methoden (früh oder spät gebunden) erzeugen eine enge Kopplung und reduzieren somit die Testbarkeit. Sie können große Programme in PHP erstellen, ohne mehr als ein paar statische Aufrufe zu verwenden. für mich sind späte statische Methoden ein Nicht-Feature.

bearbeiten Antwort auf Marco Demaios Frage, Wie reduziert die statische Methode die Testbarkeit?

Es tut mir leid, wenn dies alles offensichtlich zu Ihnen, statischen Elementen (beiden Daten und Methoden) sind nützlich und keinen Schaden anrichten, wenn verantwortungsvoll genutzt, i ihren vorherrschenden Missbrauch anspielte.

sagen Sie, Sie haben eine Webanwendung, die eine SQL-Datenbank verwendet. Ihre Geschäftsobjekte können Daten unter Verwendung einer statischen Schnittstelle oder durch Polymorphie abrufen. entweder

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

oder

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

letztere ist einfacher zu testen (wie in: i dass aus den und solchen Eingaben die SQL-Zeichenfolge aufgebaut testen will, ist so und so weiter), weil Es ist einfacher, eine andere Implementierung der dbconn Schnittstelle zu erstellen, als die Bedeutung von db:: zu ändern. Warum willst du beides?weil Sie keine echte Datenbank benötigen, um das sql-composing-Verhalten zu testen, und tatsächlich ist es einfacher, auf ohne eine echte Datenbank zu testen. Außerdem ist es einfacher, den SQL-Consumer auszugeben, wenn sich Ihre Tests auf einen anderen Aspekt des CUT beziehen (Code Under Test).

Testen bedeutet immer Lügen zu den getesteten Code über seine Mitarbeiter, und Enthaltung von statischen Schnittstellen (die "Doublecolon" oder "Quadridot") bedeutet, dass die Lüge nicht eine massive Operation sein muss, die ein Plus ist, da die weiter Der getestete Code stammt aus dem Produktionscode, je weniger aussagekräftig die Testergebnisse sind.

+0

+1 Seit ich Instanzen über statische Methoden verwende, werden die Dinge viel einfacher –

+0

@just someone: was meinst du, wenn du sagst, dass statische Methoden enge Kopplungen erzeugen, die die Testbarkeit reduzieren? Ich verstehe nicht, wie sie die Testbarkeit reduzieren können. –

+0

@Marco Demaio: siehe die bearbeitete Antwort. –

1

Wo ich eine späte statische Bindung verwenden muss, ist das Mocking von statischen Methoden für Komponententests mit PHPUnit. Das Problem, das ich habe, ist, dass ich Code nicht streng ändern möchte, um zu erlauben, zu spotten, aber ich kann darüber hinwegkommen.

Um Ihre Frage zu beantworten, würde ich jedoch wetten, dass, was auch immer die Leistung kostet, es im Vergleich zu den meisten Programmlaufzeiten verblassen wird. Mit anderen Worten, es wird keinen merklichen Unterschied machen.

Verwandte Themen