编程语言
首页 > 编程语言> > 通过PHPdoc继承抽象方法的返回类型变窄导致PHP错误

通过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