2008-09-17 6 views

ответ

5

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

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

Если вы хотите узнать больше об этой теме:

+1

Было бы полезно, если бы вы могли добавить * почему * в этом случае использование `` `static ::` `` было бы лучше или проще, чем просто использовать абстрактный, * нестатический * метод.Мне кажется, что `` `save()` `` - это то, что в любом случае у вас нет причин звонить из статического контекста, но, возможно, я что-то упускаю. – SeldomNeedy 2015-03-30 18:20:12

1

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

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

5

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

Этот 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 уменьшает это дублирование и обеспечивает гораздо более чистые и более прямые реализации.

3

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

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

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

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

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

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

1

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

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

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

Это мой опыт работы с PHP 5.2.8 - LSB собирается ввести в 5.3

0

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

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