Почему переопределение параметров метода является нарушением строгих стандартов в PHP?

Я знаю, что в StackOverflow есть несколько подобных вопросов, как этот вопрос .

Почему переопределение параметров метода является нарушением строгих стандартов в PHP? Например:

class Foo { public function bar(Array $bar){} } class Baz extends Foo { public function bar($bar) {} } 

Строгие стандарты: декларация Baz :: bar () должна быть совместима с декларацией Foo :: bar ()

На других языках программирования ООП вы можете. Почему это плохо в PHP?

В ООП SOLID означает единую ответственность, Open-closed, замену Лискова, сегрегацию интерфейса и инверсию зависимостей .

Принцип подстановки Лискова гласит, что в компьютерной программе, если Bar является подтипом Foo , тогда объекты типа Foo могут быть заменены объектами типа Bar без изменения каких-либо желательных свойств этой программы (правильность, выполняемая задача и т. Д. ).

В сильно типизированных языках программирования при переопределении метода Foo, если вы меняете подпись в баре, вы фактически перегружаетесь, поскольку исходный метод и новый метод доступны с разными сигнатурами. Поскольку PHP слабо типизирован, этого достичь невозможно, потому что компилятор не может знать, какой из методов вы на самом деле вызываете. (отсюда причина, по которой у вас не может быть 2 метода с тем же именем, даже если их подписи разные).

Таким образом, чтобы избежать нарушения принципа Liskov Substitition, выдается строжайшее стандартное предупреждение, говорящее программисту, что что-то может сломаться из-за изменения сигнатуры метода в дочернем классе.

Я знаю, что опаздываю на вечеринку, но ответы на самом деле не говорят о реальной проблеме.

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

Подсказка помогает. но в PHP он очень ограничен. Не знаю, почему. Например, вы не можете намекать, что переменная – это int или Boolean yet array. Иди цифра!

Другие объектно ориентированные языки реализуют это с помощью перегрузки функций. То есть сигнатура функции явно отличается.

Так, например, если бы следующее было возможно, у нас не было бы проблемы

 class Foo { public function bar(Array $bar){ echo "Foo::bar"; } } class Baz extends Foo { public function bar(int $bar) { echo "Baz::bar"; } } $foo = new Baz(); $bar = new Baz(); $ar = array(); $i = 100; $foo->bar($ar); $bar->bar((int)$i); would output Foo::bar Baz::bar 

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

Что глупо.

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

У меня всегда есть максимальные предупреждения при разработке кода, я никогда не позволяю предупреждению идти, не понимая, что это значит и каковы последствия. Лично я не забочусь об этом предупреждении. Я знаю, что хочу, и PHP не делает это правильно. Я пришел сюда, чтобы найти способ выборочно подавить его. Я еще не нашел пути.

Поэтому я задержу это предупреждение и подавляю его сам. Позор мне нужно сделать. но я строго отношусь к STRICT.

Вы можете переопределить параметры, но подпись должна соответствовать. Если бы вы поставили Array перед $bar , проблем не было бы.

Например, если бы вы добавили дополнительный параметр, проблем не возникло бы, если бы первый параметр имел однотипный намек. Это хорошая практика на любом языке.

Поскольку вы объявили на Foo что $bar должен иметь array типов, в то время как в расширяющемся $bar тип $bar не объявляется.

Это не ошибка, это предупреждение. Вы должны сделать определение метода совместимым с исходным базовым классом. Вы можете, однако, смело игнорировать его, если знаете, что делаете (и только если вы знаете, что делаете !!!)