Что такое позднее статическое связывание

Позднее статическое связывание в PHP (Часть II: Практика)

Что такое позднее статическое связывание. Смотреть фото Что такое позднее статическое связывание. Смотреть картинку Что такое позднее статическое связывание. Картинка про Что такое позднее статическое связывание. Фото Что такое позднее статическое связываниеПервую часть читайте здесь.

Теперь приступим к практике. Наиболее показательным примером использования LSB, по-моему, является случай, когда у вас есть набор классов выполняющих похожие действия. В терминах веб-разработки мы часто встречаемся с такими задачами при обращениях к таблицам базы данных, особенно в ORM системах. Все ваши объекты для работы с таблицами будут похожи по сути, но при этом будут иметь собственный функционал ( и, соответственно, свои подклассы).

Допустим, у нас в системе есть класс Storable, который реализует (как вы догадались) (прим. переводчика: я не догадался 🙂 ) паттерн Storable. Мы определяем классы, которые наследуются от класса Storable и задаем имена таблиц в конструкторах. Вот как это выглядит:

Можете пропустить подробности конструктора, он приведен только для того, чтобы вы представляли как работает класс Storable. Как вы уже успели понять, это сэкономит нам немного времени и позволит не тратить его на такие мелочи как простые запросы SELECT, INSERT и UPDATE.

В нашей системе, помимо основной таблицы Статьи (ArticleEntry), будут использоваться еще несколько таблиц, которые содержат мета-данные (в отношении многие-к-одному), например: теги, вложения. Мне также нужен простой способ удаления данных из под-таблиц, прежде чем обновлять данные в основной таблице (проще удалить мета-данные и создать заново, чем беспокоится о синхронизации данных). Итак, чтобы смоделировать код наиболее приближенный к схеме базы данных, я остановился на такой реализации:

Весь фокус в методе purge(). Свойство $this->tableName является защищенным свойством, которое мы получили от класса Storable. Вот пример использования:

У меня есть куча таких мелких классов для работы с таблицами мета-данных. К сожалению, поскольку наша система использует PHP версии 5.2, я не мог использовать функциональность LSB описанную в первой части статьи. И чтобы удалять мета-данные, я должен писать:

Если посмотрите выше, как определен метод purge(), то увидите, что tableName он получает из класса Storable, который получает его из конструкторов классов-потомков. Помимо этих тривиальных (но абсолютно необходимых) данных, а также получения объекта базы данных в $this->db, мы не достигли ничего создавая объект класса articleentryattachment. Код был бы намного понятнее и чище ( и конечно эффективнее), если бы можно было бы вызвать метод purge() статически. Рассмотрим такой код:

Первое, что, я надеюсь, вы заметили, это то что ArticleEntryAttachment стал намного проще. Теперь нет необходимости переопределять конструктор для подклассов, потому, что конструктор родительского класса самодостаточен. И теперь можно использовать метод purge() (используя LSB):

Поскольку, теперь purge() может получать имя таблицы, которое определяется в момент выполнения, мы можем сделать его статическим. В итоге, код — чище, выполнение — эффективней, поддержка (например, добавление новых под-классов) — пустяковая, потому как избыточность полностью убрана. Спасибо разработчикам PHP за то что это стало возможным!

Источник

Русские Блоги

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

Что такое поздняя статическая привязка

Глядя на исходный код некоторого фреймворка или код определенного проекта, вы часто можете увидеть использование поздней статической привязки.
. Например, следующий абзац:

Здесь используется поздняя статическая привязка. Итак, что такое позднее статическое связывание?

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

Как следует из названия, перед вызовом без пересылки стоит имя класса, поэтому вызываемая функция должна принадлежать «этому классу» и ее не нужно передавать другому классу. Вызов переадресации происходит из-за статической привязки на ранней стадии, которая может «пересылать другим классам», когда статический метод вызывается позже.

В официальной документации PHP говорится о позднем статическом связывании: Принцип работы позднего статического связывания заключается в том, чтобы сохранить имя класса в предыдущем «неперенаправленном вызове». Это означает, что когда мы вызываем перенаправленный статический вызов, фактически вызываемый класс является предыдущим неперенаправленным классом вызова.

Посмотрите на два примера:

Приведенный выше код выведет

Приведенный выше код выведет

Здесь в основном анализируется следующий пример 2.

1. C :: test (), это вызов без пересылки, потому что :: имеет имя класса C перед ним.

5. Теперь выполните self :: foo (), это вызов переадресации, как parent :: foo (), поэтому C также выводится.

Преимущества использования позднего статического связывания

Поздняя статическая привязка в настоящее время используется при создании экземпляра объекта. При создании экземпляра объекта static будет определять созданный объект на основе класса, вызываемого во время выполнения, а self будет определять объект на основе местоположения объекта. Создайте экземпляр объекта. Когда мы хотим только создать экземпляр подкласса и не хотим, чтобы последующее использование подкласса влияло на подкласс из-за изменений в родительском классе, поздняя статическая привязка может сыграть свою роль.

Источник

Что такое позднее статическое связывание

I have implemented enum using late static binding.

interface IEnum <
/**
* Only concrete class should implement this function that should behave as
* an enum.
*
* This method should return the __CLASS__ constant property of that class
*
* @return string __CLASS__
*/
public static function who ();
>

abstract class Enum <

// use of late static binding to get the class.
$class = static:: who ();

class Fruits extends Enum implements IEnum <

public static function who () <
return __CLASS__ ;
>
>

// user input from dropdown menu of fruits list
$input = 3 ;

echo B :: constructor (); // B
?>

Just a quick reminder to always check your syntax. While I love LSB, I thought it wasn’t working:

static::$sKey = not set

…until I realized that I’d completely forgotten to make it a variable variable:

static::$$sKey = is set

…of course this applies anywhere in PHP, but because of the (current) newness late static bindings, I’ve seen lots of code with this particular snafu in it from others.

This function can be used as a workaround for late static binding in PHP >= 5.1.0. There was another similar version of this function elsewhere, but used eval.

You can pass arguments to your constructor through your getInstance method, assuming you are running php5.

This would pass the params to your constructor. Love for php.

I discovered an interesting thing. The class name string must be accessed directly from «flat» variable. Late static binding code that get’s it’s variable from array that is passed by class instance, throws an syntax error. Bug?

public static function numbers ()
<
return 123 ;
>

$arr = array( ‘class’ => ‘A’ );

In the above example (#3) in order to make it work, you can change the child’s method from ‘private’ to ‘protected’ (or public) and it will be called through ‘static’.

class B extends A <
/* foo() will be copied to B, hence its scope will still be A and
* the call be successful */
>

class C extends A <
protected function foo () < //note the change here
echo ‘hello world!’ ;
>
>

At least as of PHP 5.3.0a2 there’s a function get_called_class(), which returns the class on which the static method is called.

class a <
static public function test () <
print get_called_class ();
>
>

a :: test (); // «a»
b :: test (); // «b»

PHP5.3 unavailable, yet in the need for ‘static’, I did the following.

Any objections? Personally I hate using the the eval() statement.

Here is a small workaround I made for the static inheritance issue. It’s not perfect, but it works.

// Init
$backTrace = debug_backtrace ();
$class = false ;

public static function staticClassName () <
// Get real name
$staticName = self :: getStatic ();

?>

There are two issues with this workaround :
— if you call a static method from global env, you need to declare the name of the class BEFORE calling the method, otherwise the workaround won’t work (see 3rd and 4th examples). But I assume good programming makes few calls to static methods from global scope, so this shouldn’t be long to fix if you use it.
— the workaround fails to access to private or protected static vars, as it uses get_class_vars(). If you find any better solution, let us know.

Источник

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

Что такое позднее статическое связывание. Смотреть фото Что такое позднее статическое связывание. Смотреть картинку Что такое позднее статическое связывание. Картинка про Что такое позднее статическое связывание. Фото Что такое позднее статическое связывание

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

C:\> php php-late-static-binding.php

My name A!
My name A!
My name A!
My name B!

Так что же здесь происходит? А вот что: когда мы в методе getNameSB() класса А определяем return static::$name мы говорим компилятору PHP, что нам нужно значение из контекста дочернего класса, а не из контекста родительского. Проще говоря, свойство берется не из того места где оно определено изначально, а из того места где оно переопределено, т.е. из дочернего класса. Вот это как раз и называется поздним статическим связыванием в PHP.

Таким образом, если Вам надо получить статические свойства (методы) из родительского класса для дочернего класса Вам необходимо использовать позднее статическое связывание в PHP, реализуемое посредством ключевого слова static.

Что такое позднее статическое связывание. Смотреть фото Что такое позднее статическое связывание. Смотреть картинку Что такое позднее статическое связывание. Картинка про Что такое позднее статическое связывание. Фото Что такое позднее статическое связывание

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

Комментарии ( 0 ):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.

Copyright © 2010-2021 Русаков Михаил Юрьевич. Все права защищены.

Источник

Что такое поздние статические привязки в PHP?

Что такое поздние статические привязки в PHP?

ОТВЕТЫ

Ответ 1

Начиная с PHP 5.3.0, PHP реализует функцию, называемую поздней статической привязкой, которая может использоваться для ссылки на вызываемый класс в контексте статического наследования.

Посмотрим на пример:

late static bindings работать, сохраняя класс, указанный в последнем «непереадресованном вызове». В случае вызовов статических методов это явно названный класс (обычно тот, который находится слева от оператора::); в случае нестатических вызовов методов это класс объекта.

Функция get_called_class() может использоваться для извлечения строки с именем вызываемого класса и static:: вводит ее область действия.

Ответ 2

Вам определенно нужно прочитать Поздние статические привязки в руководстве по PHP. Тем не менее, я постараюсь дать вам краткое резюме.

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

Ответ 3

Существует не очень очевидное поведение:

Следующий код создает «alphabeta».

Однако, если мы удалим объявление функции classname из бета-класса, в результате получим «alphaalpha».

Ответ 4

Я цитирую из книги: «PHP Master написать передовой код».

Позднее статическое связывание было добавлено в php 5.3. Это позволяет нам наследовать статические методы от родительского класса и ссылаться на вызываемый дочерний класс.

Это означает, что вы можете иметь абстрактный класс со статическими методами и ссылаться на конкретные реализации дочернего класса, используя нотацию static :: method() вместо self :: method().

Мы видим родительский класс (автомобиль) и детский класс (автомобиль). Родительский класс имеет 2 открытых метода:

Родительский класс также имеет 2 приватных метода:

Дочерний класс переопределяет 2 метода:

Теперь давайте вызовем публичные методы:

Ключевое слово static используется в шаблоне проектирования Singleton. Смотрите ссылку: https://refactoring.guru/design-patterns/singleton/php/example

Ответ 5

Ответ 6

Ответ 7

Глядя на это из «почему я должен использовать это?» перспектива, это в основном способ изменить контекст, из которого интерпретируется/запускается статический метод.

Ответ 8

Также смотрите, обновляете ли вы статические переменные в дочерних классах. Я нашел этот (несколько) неожиданный результат, когда дочерний B обновляет дочерний C:

Вы можете исправить это, объявив одну и ту же переменную в каждом дочернем классе, например:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *