Предположим, у нас есть следующая цепочка наследования в PHP
abstract class Entity {}
abstract class RealEntity extends Entity {}
abstract class PseudoEntity extends Entity {}
и куча других классов, которые отражают ту же цепочку наследования
abstract class EntitySerializer {
/**
* @return Entity
*/
abstract public function getEntity();
}
abstract class RealEntitySerializer extends EntitySerializer {
/**
* @return RealEntity
*/
abstract public function getEntity();
}abstract class PseudoEntitySerializer extends EntitySerializer {
/**
* @return PseudoEntity
*/
abstract public function getEntity();
}
PHP жалуется, что абстрактный метод getEntity
либо должны быть правильно реализованы (и потерять abstract
ключевое слово) или не должны быть повторно объявлены. Я могу понять, почему PHP жалуется, потому что, несмотря на комментарии PHPdoc, подпись метода идентична подписи родительского метода в EntitySerializer
,
Тем не менее, я хочу как-то прояснить, что дочерние классы, которые расширяют RealEntitySerializer
или же PseudoEntitySerializer
не должен возвращать экземпляр произвольного Entity
но сузить тип возвращаемого значения RealEntity
или же PseudoEntity
соответственно
Особенно, если я опускаю переопределение метода и соответствующего ему PHPdoc из промежуточных классов, чтобы сделать PHP счастливым, моя IDE правильно предполагает, что RealEntitySerializer::getEntity
а также PseudoEntitySerializer::getEntity
разрешено возвращать произвольный экземпляр Entity
, В результате моя среда IDE жалуется, что я вызываю неопределенные методы, если вызываю методы, относящиеся к одному из промежуточных классов объекта, который был возвращен RealEntitySerializer::getEntity
или же PseudoEntitySerializer::getEntity
соответственно
Как мне достичь обеих целей? Код, который (а) интерпретируется PHP без ошибок и (б) должным образом документирован.
Вы хотите PSR-5: PHPDoc @method
тег.
@method [return type] [name]([type] [parameter], [...]) [description]
/**
* @method string getString()
* @method void setInteger(int $integer)
* @method setString(int $integer)
*/
class Child extends Parent
{
<...>
}
abstract class EntitySerializer {
/**
* @return Entity
*/
abstract public function getEntity();
}
/**
* @method RealEntity getEntity()
*/
abstract class RealEntitySerializer extends EntitySerializer {}
/**
* @method PseudoEntity getEntity()
*/
abstract class PseudoEntitySerializer extends EntitySerializer {}
Других решений пока нет …