После прочтения this description поздней статической привязки (LSB) Я довольно четко вижу, что происходит. Теперь, при каких обстоятельствах это может быть самым полезным или необходимым?Когда вам понадобится использовать позднюю статическую привязку?
ответ
мне нужен LSB это для следующего сценария:
- Imagine вы создаете «почтовый процессор» демон, который загружает сообщения с почтового сервера, классифицирует его, анализирует его, сохраняет его, а затем делает что-то, в зависимости от типа сообщения.
- Иерархия классов: у вас есть базовый класс сообщений с детьми «BouncedMessage» и «AcceptedMessage».
- Каждый из типов сообщений имеет свой собственный способ сохранения на диске. Например, все сообщения типа BouncedMessage пытаются сохранить себя как BouncedMessage-id.xml. AcceptedMessage, с другой стороны, должен сохранять себя по-другому - как AcceptedMessage-timestamp.xml. Важно то, что логика для определения шаблона имени файла различна для разных подклассов, но разделяет для всех элементов подкласса. Вот почему имеет смысл использовать статический метод.
- Базовый класс сообщений имеет абстрактный статический метод (да, аннотация И статические) «сохранить». BouncedMessage реализует этот метод с помощью конкретного статического метода. Затем, внутри класса, который фактически извлекает сообщение, вы можете вызвать ":: Save()"
Если вы хотите узнать больше об этой теме:
Если вам нужно получить доступ к перегруженному статическому свойству/методу в рамках метода, который не был перегруженный в подклассе - вам нужно использовать позднюю статическую привязку. Быстрый пример: paste2.org
Классическим примером является класс ActiveRecord из Rails, если вы пытаетесь реализовать что-то подобное в PHP, который будет выглядеть следующим образом: class User extends ActiveRecord
, а затем попытаться вызвать User::find(1)
метод, который вызывается на самом деле ActiveRecord::find()
потому что вы не перегрузили find()
в User
- но без поздней статической привязки метод find()
в ActiveRecord
не имеет способа узнать, с какого класса он вызван (self
в нем всегда указывается ActiveRecord
), и поэтому он не может получить ваши Пользовательский объект для вас.
Одна из основных проблем, которые у меня возникают для поздней статической привязки, - это набор статических методов создания экземпляров.
Этот DateAndTime class является частью библиотеки хронологии, которую я портировал на 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);
}
}
Поскольку количес r методов создания экземпляров и иерархии классов увеличивает дублирование методов становится настоящей болью в прикладе. LSB уменьшает это дублирование и обеспечивает гораздо более чистые и более прямые реализации.
Это полезно, когда:
У вас есть функциональность, которая изменяется по иерархии классов,
Функциональность имеет ту же сигнатуру по иерархии, и
(самое главное) Вы у вас нет экземпляра, чтобы отключить функциональность.
Если получены только # 1 и # 2, вы должны использовать обычный метод экземпляра. Поэтому проблема Алекса (см. Его ответ на этот вопрос) не требует LSB.
Типичный случай - создание объекта, где подклассы создают себя по-разному, но с использованием тех же параметров. Очевидно, что у вас нет экземпляра для вызова, поэтому метод создания (также известный как заводский метод) должен быть статическим. Тем не менее вы хотите, чтобы его поведение менялось в зависимости от подкласса, поэтому обычный статический метод неверен. См. Ответ Адама Франко для примера.
Предположим, что у вас есть классы, представляющие таблицы (экземпляры строк) в упрощенном объектно-реляционном сопоставлении. У вас будет класс «Пользователь» и класс «Компания», экземпляры которого представляют строки соответствующих таблиц. Пользователь и компания наследуют от базового абстрактного класса, скажем, «BaseObject», который будет иметь некоторые общие методы, такие как save(), delete(), validate() и т. Д.
Если вы хотите сохранить данные о валидация и определение таблицы, лучшее место было бы в статической переменной в каждом производном классе, поскольку определение валидации и таблицы одинаково для каждого экземпляра пользователя.
Без LSB указанный метод validate() в BaseObject не будет ссылаться на статические переменные, определенные пользователем и компанией, даже если вы вызываете его через экземпляр пользователя. Он будет искать одну и ту же статическую переменную в классе BaseObject, и это вызовет ошибку.
Это мой опыт работы с PHP 5.2.8 - LSB собирается ввести в 5.3
У меня есть класс со статическим методом, который обрабатывает форматирование. У меня есть другой класс, который требует всех функциональных возможностей оригинала, кроме того, как он обрабатывает форматирование.
- 1. PHP: Когда вам понадобится ключевое слово self ::?
- 2. Когда вам понадобится переменная открытого экземпляра?
- 3. Когда вам когда-либо понадобится изменить значение первичного ключа?
- 4. Невозможно инициировать позднюю привязку нокаута
- 5. Когда вам понадобится несколько серверов для размещения одного веб-приложения?
- 6. Свойства оси XML не поддерживают позднюю привязку
- 7. Excel VBA: ссылка на позднюю привязку
- 8. Есть ли причина, по которой Java использует позднюю/статическую привязку для перегруженных методов в одном классе?
- 9. Сколько времени вам понадобится, чтобы узнать backbone.js
- 10. Возможно, вам понадобится поддержка API Карт Google?
- 11. Когда мне понадобится использовать encodeSystemFieldsWithCoder из CKRecord?
- 12. Когда использовать статическую привязку и когда использовать динамическое связывание в Java?
- 13. Когда использовать WCF-привязку
- 14. Когда понадобится $ DLN_LIBRARY_PATH?
- 15. Когда мне понадобится TransactionScopeOption.Supress?
- 16. Когда понадобится рубиновый триггер?
- 17. Что я буду использовать, когда вам понадобится динамически настраиваемый многопользовательский список?
- 18. Когда использовать статическую функцию-член?
- 19. Когда нам понадобится непостоянное предпочтение?
- 20. Когда следует использовать привязку шаблона?
- 21. Когда использовать и не использовать статическую функцию?
- 22. Когда мне понадобится виртуальная функция?
- 23. FileHelpers Master/Detail - Option Strict On запрещает позднюю привязку
- 24. WPF DataGridRow.Item ("xx") - опция Strict On запрещает позднюю привязку
- 25. Когда мне понадобится использовать бинарный поиск вместо линейного поиска?
- 26. Когда нам понадобится механизм шаблона клиента javascript?
- 27. Зачем вам когда-либо использовать count ('foo')?
- 28. Когда вам действительно нужно использовать Flash?
- 29. Зачем вам когда-либо использовать $ rootScope?
- 30. Когда вам нужно использовать контроллер вида?
Было бы полезно, если бы вы могли добавить * почему * в этом случае использование `` `static ::` `` было бы лучше или проще, чем просто использовать абстрактный, * нестатический * метод.Мне кажется, что `` `save()` `` - это то, что в любом случае у вас нет причин звонить из статического контекста, но, возможно, я что-то упускаю. – SeldomNeedy 2015-03-30 18:20:12