Intereting Posts
Создайте рейтинг Определить часовой пояс пользователя и отобразить время UTC с этим часовым поясом php-массив побитовый PHP – Как конвертировать URL-адрес YouTube с помощью Regex Как я могу исправить флеш-флагом PHP-потокобезопасное / непоточное безопасное рассогласование? Можно ли проверить, приведет ли imagecreatefromjpeg к тому, что память исчерпала фатальную ошибку, прежде чем запускать ее? SabreDAV + Nginx + PUT (создает 0 байтовый файл) Функция php mail не отправляет электронные письма / слишком долго, чтобы отправлять электронные письма Фильтровать XML по элементам Тернарные операторы и переменная переназначения в PHP API USPS возвращает код ошибки 80040B19, а учетная запись находится в разделе «Производство» Вставить «элемент» среди других «элементов» массива (loop) php Создание PDF-помощника для CakePHP 2.0 с использованием TCPDF загрузить ход с последующей обработкой как загрузить аудиофайл на сервер (базу данных mysql) с помощью phonegap.?

Когда вам понадобится использовать позднюю статическую привязку?

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

Мне нужен LSB для следующего сценария:

  • Представьте, что вы создаете демона «почтового процессора», который загружает сообщение с почтового сервера, классифицирует его, анализирует, сохраняет его и затем выполняет что-то в зависимости от типа сообщения.
  • Иерархия классов: у вас есть базовый класс сообщений с дочерними элементами «BouncedMessage» и «AcceptedMessage».
  • Каждый из типов сообщений имеет свой собственный способ сохранения на диске. Например, все сообщения типа BouncedMessage пытаются сохранить себя как BouncedMessage-id.xml. AcceptedMessage, с другой стороны, должен сохранять себя по-другому – как AcceptedMessage-timestamp.xml. Важно то, что логика для определения шаблона имени файла отличается для разных подклассов, но используется для всех элементов в подклассе. Вот почему имеет смысл использовать статический метод.
  • Базовый класс сообщений имеет абстрактный статический метод (да, абстрактный И статический) «сохранить». BouncedMessage реализует этот метод с помощью конкретного статического метода. Затем внутри класса, который действительно извлекает сообщение, вы можете вызвать «:: save ()»

Если вы хотите узнать больше о предмете:

Одна из основных проблем, которые я испытываю для поздней статической привязки, – это набор статических методов создания экземпляров.

Этот класс DateAndTime является частью библиотеки хронологии, которую я портировал на PHP из Smalltalk / Squeak. Использование статических методов создания экземпляров позволяет создавать экземпляры с различными типами аргументов, сохраняя при этом проверку параметров в статическом методе, чтобы потребитель библиотеки не смог получить экземпляр, который не является полностью действительным.

Позднее статическое связывание полезно в этом случае, так что реализации этих статических методов создания экземпляров могут определять, из какого класса изначально был направлен вызов. Вот пример использования:

С LSB:

 class DateAndTime { public static function now() { $class = static::myClass(); $obj = new $class; $obj->setSeconds(time()); return $obj; } public static function yesterday() { $class = static::myClass(); $obj = new $class; $obj->setSeconds(time() - 86400); return $obj; } protected static function myClass () { return 'DateAndTime'; } } class Timestamp extends DateAndTime { protected static function myClass () { return 'Timestamp'; } } // Usage: $date = DateAndTime::now(); $timestamp = Timestamp::now(); $date2 = DateAndTime::yesterday(); $timestamp2 = Timestamp::yesterday(); 

Без поздней статической привязки [как и в моей текущей реализации] каждый класс должен реализовать каждый способ создания экземпляра, как в этом примере:

Без LSB:

 class DateAndTime { public static function now($class = 'DateAndTime') { $obj = new $class; $obj->setSeconds(time()); return $obj; } public static function yesterday($class = 'DateAndTime') { $obj = new $class; $obj->setSeconds(time() - 86400); return $obj; } } class Timestamp extends DateAndTime { public static function now($class = 'Timestamp') { return self::now($class); } public static function yesterday($class = 'Timestamp') { return self::yesterday($class); } } 

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

Это полезно, когда:

  1. У вас есть функциональность, которая зависит от иерархии классов,

  2. Функциональность имеет одну и ту же подпись по иерархии и

  3. (критически) У вас нет экземпляра, чтобы отключить функциональность.

Если получены только # 1 и # 2, вы должны использовать обычный метод экземпляра. Поэтому проблема Алекса (см. Его ответ на этот вопрос) не требует LSB.

Типичным случаем является создание объекта, где подклассы создают себя по-разному, но используют одни и те же параметры. Очевидно, что у вас нет экземпляра для вызова, поэтому метод создания (также известный как заводский метод) должен быть статическим. Тем не менее вы хотите, чтобы его поведение менялось в зависимости от подкласса, поэтому обычный статический метод неверен. См. Ответ Адама Франко для примера.

Если вам нужно получить доступ к перегруженному статическому свойству / методу в методе, который не был перегружен в подклассе, вам потребуется поздняя статическая привязка. Быстрый пример: paste2.org

Классическим примером является класс ActiveRecord из Rails, если вы попытаетесь реализовать что-то подобное в PHP, которое будет выглядеть так: class User extends ActiveRecord а затем пытается вызвать User::find(1) метод, который вызывается, фактически является ActiveRecord::find() потому что вы не перегрузили find() в User но без поздней статической привязки метод find() в ActiveRecord не имеет способа узнать, из какого класса он вызван (изнутри внутри всегда будет указываться ActiveRecord ) , и, следовательно, он не может получить ваш Пользовательский объект для вас.

Предположим, что у вас есть классы, представляющие таблицы (экземпляры строк) в упрощенном объектно-реляционном сопоставлении. У вас будет класс «Пользователь» и класс «Компания», экземпляры которого представляют строки соответствующих таблиц. Пользователь и компания наследуют от базового абстрактного класса, скажем, «BaseObject», который будет иметь некоторые общие методы, такие как save (), delete (), validate () и т. Д. …

Если вы хотите хранить данные о проверке и определении таблицы, лучшим местом будет статическая переменная в каждом производном классе, поскольку определение валидации и таблицы одинаково для каждого экземпляра пользователя.

Без LSB упомянутый метод validate () в BaseObject не будет ссылаться на статические переменные, определенные в User and Company, даже если вы вызываете его через экземпляр User. Он будет искать одну и ту же статическую переменную в классе BaseObject, и это вызовет ошибку.

Это мой опыт работы с PHP 5.2.8 – LSB будет представлен в 5.3

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