Я думаю, будет легче увидеть проблему в примере кода, чем писать вопрос в первую очередь. Вот мой 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
.
Это сложно, но это легче понять, если вы видите пример.