通过PHPdoc继承抽象方法的返回类型变窄导致PHP错误
作者:互联网
假设我们在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 resp.
特别是,如果我省略了中间类的方法及其对应的PHPdoc的重新定义以使PHP满意,则我的IDE会正确地假定RealEntitySerializer :: getEntity和PseudoEntitySerializer :: getEntity被允许返回Entity的任意实例.结果,我的IDE抱怨说,如果我调用RealEntitySerializer :: getEntity或PseudoEntitySerializer :: getEntity resp返回的对象中的某个中间类特定的方法,则会调用未定义的方法.
如何实现两个目标? (a)由PHP解释且无错误且(b)正确记录的代码.
解决方法:
您需要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 {}
标签:php,inheritance,phpdoc,type-narrowing 来源: https://codeday.me/bug/20191013/1909694.html