Я думаю, будет легче увидеть проблему в примере кода, чем писать вопрос в первую очередь. Вот мой php-код:
<?php interface AnInterface { public function method(); } class AClass implements AnInterface { public function method() { echo __METHOD__; } } abstract class AnAbstractClass { abstract public function method( AnInterface $Object ); } class ConcreteClass extends AnAbstractClass { public function method( AClass $Object ) { $Object->method(); } } $Object1 = new ConcreteClass(); $Object2 = new AClass(); $Object1->method( $Object2 );
Вышеприведенный код вызывает следующую ошибку:
Неустранимая ошибка: объявление ConcreteClass :: method () должно быть совместимо с объявлением AnAbstractClass :: method ()
Проблема в том, что php, похоже, не распознает подписи метода AnAbstractClass :: method и ConcreteClass :: как совместимые. Я делаю что-то неправильно? Благодаря!
php, похоже, не распознает подписи метода
AnAbstractClass::methodиConcreteClass::methodкак совместимые.
PHP правильный, они несовместимы. AClass только экземпляры AClass (или его дочерних AClass ) для передачи в ConcreteClass::method , вы нарушаете контракт, который предоставляет AnAbstractClass : Любой из его подклассов должен принять AnInterface в качестве аргумента для своего method() .
Если ваш пример работал, и у меня был другой класс BClass реализующий AnInterface , у нас была бы ситуация, когда согласно AnAbstractClass method() должен принимать экземпляры BClass , в то время как, согласно ConcreteClass , он не должен.
Измените свою подпись для ConcreteClass::method чтобы она соответствовала AnAbstractClass::method .
Не считается. Вчера у нас было такое же обсуждение:
Могут ли типы параметров быть специализированными в PHP
Все ваши производные классы должны одинаково реализовывать подписи метода.
Это то, что в идеале должно быть проверено во время выполнения. Но в PHP парсер делает. (Чтобы компенсировать, PHP не проверяет доступ к закрытому / защищенному атрибуту во время разбора, но пусть это скорее взорвется во время выполнения.)
Если вы хотите применить более строгий тип, я бы посоветовал:
assert( is_a($Object, "AClass") );
Вот пример, который показывает, почему это не разрешено:
<?php class BClass implements AnInterface { } function moo(AnAbstractClass $abstract) { $b = new BClass(); $abstract->method($b); }:<?php class BClass implements AnInterface { } function moo(AnAbstractClass $abstract) { $b = new BClass(); $abstract->method($b); }
Это был бы допустимый код, но он потерпит неудачу, если вы передадите ConcreteClass в moo, потому что его метод ConcreteClass::method не позволяет BClass .
Это сложно, но это легче понять, если вы видите пример.