После включения строгих предупреждений в PHP 5.2 я увидел множество предупреждений о строгих стандартах из проекта, который изначально был написан без строгих предупреждений:
Строгие стандарты : статическая функция Program :: getSelectSQL () не должна быть абстрактной в Program.class.inc
Рассматриваемая функция принадлежит абстрактному родительскому классу Program и объявляется абстрактным статическим, поскольку она должна быть реализована в своих дочерних классах, таких как TVProgram.
Я нашел ссылки на эти изменения здесь :
Отброшены абстрактные статические функции класса. По недосмотру PHP 5.0.x и 5.1.x разрешили абстрактные статические функции в классах. Начиная с PHP 5.2.x, они могут быть только в интерфейсах.
У меня вопрос: может ли кто-нибудь четко объяснить, почему в PHP не должно быть абстрактной статической функции?
Ответы:
статические методы принадлежат тому классу, который их объявил. При расширении класса вы можете создать статический метод с тем же именем, но на самом деле вы не реализуете статический абстрактный метод.
То же самое касается расширения любого класса статическими методами. Если вы расширите этот класс и создадите статический метод с той же сигнатурой, вы фактически не переопределите статический метод суперкласса
РЕДАКТИРОВАТЬ (16 сентября 2009 г.)
Обновление по этому поводу. Запустив PHP 5.3, я вижу, что абстрактная статика вернулась, хорошо это или плохо. (см. http://php.net/lsb для получения дополнительной информации)
КОРРЕКЦИЯ (по philfreo)
abstract static
до сих пор не разрешены в PHP 5.3, LSB связано , но отличается.источник
abstract static
может быть полезно в этом случае.Это долгая печальная история.
Когда PHP 5.2 впервые представил это предупреждение, поздние статические привязки еще не были в языке. Если вы не знакомы с поздними статическими привязками, обратите внимание, что такой код работает не так, как вы могли ожидать:
Не говоря уже о предупреждении о строгом режиме, приведенный выше код не работает.
self::bar()
Вызов вfoo()
явном виде относится кbar()
способуParentClass
, даже когдаfoo()
вызываются в качестве методаChildClass
. Если вы попытаетесь запустить этот код с выключенным строгим режимом, вы увидите сообщение « Неустранимая ошибка PHP: невозможно вызвать абстрактный метод ParentClass :: bar ()». ».Учитывая это, абстрактные статические методы в PHP 5.2 были бесполезны. Вся точка использования абстрактного метода является то , что вы можете написать код , который вызывает метод , не зная , что реализация это будет вызов - а затем предоставить различные реализации на разных классах детей. Но поскольку PHP 5.2 не предлагает чистого способа написать метод родительского класса, который вызывает статический метод дочернего класса, для которого он вызывается, такое использование абстрактных статических методов невозможно. Следовательно, любое использование
abstract static
в PHP 5.2 является плохим кодом, вероятно, вызванным непониманием того, какself
работает ключевое слово. Было вполне разумно сделать предупреждение по этому поводу.Но затем появился PHP 5.3, добавивший возможность ссылаться на класс, для которого был вызван метод, через
static
ключевое слово (в отличие отself
ключевого слова, которое всегда относится к классу, в котором был определен метод ). Если вы измените значениеself::bar()
наstatic::bar()
в моем примере выше, он отлично работает в PHP 5.3 и выше. Вы можете узнать больше оself
vsstatic
на New self vs. new static .С добавлением ключевого слова static явным аргументом в пользу наличия
abstract static
исчез выдачи предупреждения. Основная цель поздних статических привязок состояла в том, чтобы позволить методам, определенным в родительском классе, вызывать статические методы, которые будут определены в дочерних классах; разрешение абстрактных статических методов кажется разумным и последовательным, учитывая наличие поздних статических привязок.Думаю, вы все еще можете убедить вас в сохранении предупреждения. Например, можно утверждать , что с PHP позволяет вызывать статические методы абстрактных классов, в моем примере выше (даже после фиксации его замены
self
сstatic
) вы обнажая публичный метод ,ParentClass::foo()
который сломан и что вы действительно не хотите разоблачить. Использование нестатического класса - то есть создание всех методов экземпляра методов и создание дочерних элементовParentClass
синглтонами или что-то в этом роде, решило бы эту проблему, посколькуParentClass
, будучи абстрактным, нельзя создать экземпляр, и поэтому его методы экземпляра не могут называться. Я считаю этот аргумент слабым (потому что я думаю, что разоблачениеParentClass::foo()
не имеет большого значения, и использование синглтонов вместо статических классов часто излишне многословно и некрасиво), но вы можете разумно не согласиться - это несколько субъективный вызов.Итак, основываясь на этом аргументе, разработчики PHP сохранили предупреждение на языке, верно?
Ну, не совсем .
В отчете об ошибке PHP 53081, ссылка на который приведена выше, содержится призыв к удалению предупреждения, поскольку добавление
static::foo()
конструкции сделало абстрактные статические методы разумными и полезными. Расмус Лердорф (создатель PHP) начинает с того, что помечает запрос как поддельный и проходит длинную цепочку неверных аргументов, чтобы попытаться оправдать предупреждение. Затем, наконец, происходит этот обмен:Утверждение Расмуса о том, что код в его примере «отлично работает», является ложным; как вы знаете, он выдает предупреждение о строгом режиме. Я думаю, он тестировал без включения строгого режима. Тем не менее, сбитый с толку Расмус оставил запрос ошибочно закрытым как «поддельный».
И поэтому предупреждение все еще на языке. Возможно, это не совсем удовлетворительное объяснение - вы, вероятно, пришли сюда в надежде, что предупреждение было рациональным. К сожалению, в реальном мире выбор порой является результатом обыденных ошибок и неверных рассуждений, а не рационального принятия решений. Это просто один из таких случаев.
К счастью, уважаемый Никита Попов удалил предупреждение из языка PHP 7 как часть PHP RFC: Reclassify E_STRICT notices . В конце концов, здравомыслие восторжествовало, и как только выйдет PHP 7, мы все сможем с радостью использовать,
abstract static
не получая этого глупого предупреждения.источник
Есть очень простой способ решения этой проблемы, который действительно имеет смысл с точки зрения дизайна. Как писал Джонатан:
Итак, в качестве обходного пути вы можете сделать это:
И теперь вы обеспечиваете, чтобы любой класс, являющийся подклассом MyFoo, реализовывал статический метод getInstance и общедоступный метод getSomeData. И если вы не создаете подкласс MyFoo, вы все равно можете реализовать iMyFoo для создания класса с аналогичной функциональностью.
источник
static::
может быть полезно.abstract static
методы, без скуки PHP ....Я знаю, что это старое, но ....
Почему бы просто не выбросить исключение в статическом методе родительского класса, таким образом, если вы не переопределите его, возникнет исключение.
источник
Я бы сказал, что абстрактный класс / интерфейс можно рассматривать как контракт между программистами. Он больше касается того, как вещи должны выглядеть / вести себя, а не реализовывать фактическую функциональность. Как видно из php5.0 и 5.1.x, это не естественный закон, который мешает разработчикам php делать это, а побуждение идти вместе с другими шаблонами проектирования OO на других языках. В основном эти идеи пытаются предотвратить неожиданное поведение, если человек уже знаком с другими языками.
источник
Я не вижу причин запрещать статические абстрактные функции. Лучший аргумент в пользу того, что нет причин запрещать их, - это то, что они разрешены в Java. Вопросы следующие: - Возможно ли это технически? - Да, поскольку они существовали в PHP 5.2 и существуют в Java. Итак, где МОЖЕТ это сделать. ДОЛЖНЫ ли мы это делать? - Есть ли в них смысл? Да. Имеет смысл реализовать часть класса и оставить другую часть класса пользователю. Это имеет смысл в нестатических функциях, почему это не имеет смысла для статических функций? Одно из применений статических функций - это классы, в которых не должно быть более одного экземпляра (синглтоны). Например, механизм шифрования. Необязательно, чтобы она существовала в нескольких экземплярах, и есть причины для предотвращения этого - например, вы должны защитить только одну часть памяти от злоумышленников. Таким образом, имеет смысл реализовать одну часть механизма и оставить алгоритм шифрования пользователю. Это только один пример. Если вы привыкли использовать статические функции, вы найдете гораздо больше.
источник
В php 5.4+ используйте трейт:
и в вашем классе поставьте с самого начала:
источник
abstract public static function get_table_name();
черту и использовать ее в своем абстрактном классе без предупреждений E_STRICT! Это все еще заставляло определять статический метод у детей, как я и надеялся. Фантастика!Изучите проблемы PHP «Поздняя статическая привязка». Если вы помещаете статические методы в абстрактные классы, вы, вероятно, столкнетесь с этим раньше, чем позже. Имеет смысл, что строгие предупреждения говорят вам избегать использования неработающих языковых функций.
источник