Позднее статическое связывание в PHP 5.3 – рассмотрим примеры

С выходом PHP 5.3 появилась функциональность “позднего статического связывания”. Многие разработчики были озадачены данной особенностью в более ранних версиях PHP, но, вероятно, не знали, что она имеет название. В данной статье рассматривается проблема, возникающая при статическом связывании и как её избежать в PHP 5.3.

Позднее статическое связывание в PHP 5.3

Позднее статическое связывание в PHP 5.3

Проблема возникает из-за способа, которым классы PHP ссылаются на текущий экземпляр класса. Ключевые слова, такие как self, получают значение во время компиляции, это означает, ключевое self всегда относится к тому классу, в котором упоминается, т.е. к родительскому классу, а не к производному. Классы имеют общую функциональность в иерархии классов, но при этом нужна возможность различать классы для доступа к имени класса или содержащейся в нём переменной, чтобы метод, объявленный в родительском классе, мог быть использован во всех производных классах. Без позднего статического связывания задача всегда будет сводиться к определению класса, оставляя разработчикам выбор между копированием кода функции в каждый класс и преобразованием статического метода в динамический, поскольку $this получает значение, как и ожидалось.

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

class Record {

protected static $tableName = 'base';

public static function getTableName() {
return self::$tableName;
}
}

Теперь можно определить пользовательский класс, он будет включать собственную переменную, но функция getTableName будет унаследована, поскольку она идентична той, которая объявлена в родительском классе.

class User extends Record {
protected static $tableName = 'users';
}

Теперь, если вызвать метод getTableName в классе User, какой бы вы ожидали результат:

User::getTableName(); // возвращает "base"

Не совсем то, что ожидалось. Это вполне обычная вещь, которую требуется сделать. Я часто видел, что люди сталкиваются с этой проблемой при реализации шаблона активной записи (Active Record), когда создают многоразовые виджеты форм в своих собственных шаблонах и приложениях. В PHP 5.3 ключевое слово static реализовано, чтобы позволить получить значение класса, код которого выполняется в данный момент, а не родительского класса. Для этого в классе Record необходимо только заменить ключевое слово “self” на “static”:

class Record {

protected static $tableName = 'base';

public static function getTableName() {
return static::$tableName;
}
}

Данное ключевое слово по-другому получает значение, учитывая контекст, из которого происходит вызов. Теперь, если повторить вызов метода getTableName в классе User.

User::getTableName(); // возвращает "users"

Так намного лучше!

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

0 Comments



You can be the first one to leave a comment.

Оставить комментарий

Нужно войти что бы оставить комменатрий.