2009-11-29 3 views
13

Начиная с версии 5.3, PHP поддерживает late binding для статических методов. Хотя это, несомненно, полезная функция, есть только несколько случаев, когда ее использование действительно необходимо (например, шаблон Active Record).Возможно ли чрезмерное статическое связывание в PHP?

Рассмотрим следующие примеры:

1. Удобство конструкторами (::create())

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

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

Если этот класс может быть расширен (однако, это не распространяется на любого класса в том же пакете), должны более поздняя статическая привязка используется просто для упрощения ее расширения (без необходимости переписывать метод ::create() и, что более важно, не задумываясь об этом)?

Примечание: эта идиома используется для устранения невозможности вызова методов только для объектов: new SimpleObject()->doStuff() недействителен в PHP.


2. Класс константы

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

Причина использовать static:: в этом примере, аналогична предыдущей. Он используется только потому, что этот класс может быть создан для соответствия разным образом сформированным тэгам, просто расширяя его и переопределяя константу.


Таким образом, чтобы обернуть все это, используются ли эти (и подобные) поздние статические привязки, являются излишним? Есть ли заметная производительность? Кроме того, частое использование позднего связывания уменьшает общий прирост производительности, предоставляемый кэшами операций операций?

+0

Ну, второе может быть достигнуто с переопределением частной переменной и с использованием '$ this' тоже, верно? Или я что-то не понимаю? – Franz

+1

Да, но я просто не мог подойти к лучшему примеру ... Наличие в качестве 'const' означает избежать копирования всех экземпляров. И даже если бы PHP-копирование-на-запись оптимизировало бы это, оно, безусловно, выглядит лучше как константа класса, потому что оно на самом деле является постоянным значением класса в целом. –

+0

... и все это на самом деле означало, что в этом случае использование переменных экземпляра выглядит как обходное решение, а 'static ::' - нет. –

ответ

13

Итак, чтобы обернуть все это, используются ли эти (и подобные) поздние статические привязки, являются излишним? Есть ли заметная производительность? Кроме того, частое использование позднего связывания уменьшает общий прирост производительности, предоставляемый кэшами операций операций?

Введение позднего статического связывания устраняет недостатки объектной модели PHP. Речь идет не о производительности, а о семантике.

Например, мне нравится использовать статические методы всякий раз, когда реализация метода не используется $this. Просто потому, что метод статичен, это не означает, что вы не хотите иногда его переопределять. До PHP 5.3 поведение было то, что ошибка была отмечена, если вы переопределили статический метод, но PHP просто продолжил бы и молча использовал версию родителя. Например, приведенный ниже код печатает «A» перед PHP 5.3. Это очень неожиданное поведение.

Последнее статическое связывание фиксирует его, и теперь тот же код печатает «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

Прокомментируйте комментарий после downvote. – erenon

+11

Я знаю, что это старый поток, но нашел его через Google. Ваш примерный код должен на самом деле печатать «A» независимо от версии PHP. Чтобы активировать поздние статические привязки, используйте ключевое слово static. НАПРИМЕР.замените self :: who(); со статическими :: who(); и он должен печатать 'B' – Maurice

3

Статические методы (ранние или поздние) создают плотную связь и (таким образом) уменьшают возможность проверки. вы можете создавать большие программы на PHP без использования нескольких статических вызовов. для меня поздние статические методы не являются функциями.

Редактировать ответить на вопрос Marco Demaio, Как сделать статический метод уменьшенным тестируемостью?

я прошу прощения, если все это очевидно для вас, статические члены (данные и методы) являются полезным и не делать никакого вреда, если они используются ответственно, я имел в виду их преобладающего использования.

говорят, что у вас есть веб-приложение, использующее базу данных SQL. ваши бизнес-объекты могут извлекать данные, используя статический интерфейс или полиморфизм. либо

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

или

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

последний легче тестировать (например: я хочу, чтобы проверить, что SQL строка строится из таких-то и таких входов такой-то), потому что проще создать другую реализацию интерфейса dbconn, чем изменить значение db::. почему вы тоже хотите?потому что вам не нужна настоящая база данных для проверки поведения sql-составления, и на самом деле легче проверить для без реальной базы данных. Кроме того, проще вырезать пользователя sql, если ваши тесты касаются другого аспекта CUT (Code In Test).

тестирование всегда подразумевает ложь проверенного кода о его сотрудниках, а воздержание от статических интерфейсов («двухцветный» или «квадридот») означает, что ложь не должна быть масштабной хирургией, что является плюсом, поскольку чем дальше проверенный код из производственного кода, тем менее значимыми являются результаты тестирования.

+0

+1 Так как я начал использовать экземпляры по статическим методам, все стало намного проще вокруг –

+0

@ just someonebody: что вы имеете в виду, когда вы говорите, что статические методы создают жесткую связь, уменьшающую тестируемость? Я не понимаю, как они могут уменьшить тестируемость. –

+0

@Marco Demaio: см. Отредактированный ответ. –

1

Где найти необходимость использования позднего статического связывания, чтобы позволить насмешливые статических методов модульного тестирования с помощью PHPUnit. Проблема у меня в том, что мне не нравится менять код строго, чтобы насмехаться, но я могу справиться с этим.

Чтобы ответить на ваш вопрос, я бы поспорил, что независимо от того, какую производительность он несет, он будет бледнее по сравнению с большинством времени выполнения программы. Другими словами, это не будет иметь заметной разницы.

Смежные вопросы