【问题标题】:PhpStorm warns about "Expected class1, got class2" when class2 extends class1当 class2 扩展 class1 时,PhpStorm 警告“预期的 class1,得到 class2”
【发布时间】:2017-01-09 12:12:25
【问题描述】:

我正在使用 Phalcon 框架,它具有模型类:Phalcon\Mvc\Model(从现在起仅作为 P\M\Model)。我已经定义了基域,它扩展了该类,然后所有其他域都扩展了我的基域,因此 Phalcons 模型类:

域名.php:

class Domain extends \Phalcon\Mvc\Model
{
    ...
}

DomainA.php:

class DomainA extends Domain
{
    ...
}

然后我使用存储库管理器获取DomainA 模型的存储库。所有存储库都有相同的父级,类似于定义了方法 find() 的 Domain

Repository.php:

class Repository
{
    /**
    * Will always return object of classes 
    * which extends Phalcon\Mvc\Model
    *
    * @return Phalcon\Mvc\Model
    */
    public function find()
    {
        ...
        $domain::find();
    }
}

RepositoryA.php:

class RepositoryA extends Repository
{
    ...
}

所以,RepositoryA 现在有来自其父级的 find() 方法,因为父级并不确切知道他将返回什么,但知道所有返回的父级,所以它通过 @ 进行类型提示987654330@.

然后我有一些其他类,它的方法只需要 DomainA 对象,它也是 P\M\Model 的父对象,我尝试将这种类型的对象推送到那里它工作正常,因为从存储库返回的对象实际上是DomainA 对象,但 Repository 将其注释为 P\M\Model,因此 PhpStorm 用消息突出显示它 "Expected DomainA, got Phalcon\Mvc\Model..."

public function pleaseGiveDomainA(DomainA $obj)
{
    ...
}

// Works OK but is higlighted in IDE
$this->pleaseGiveDomainA($repositoryA->find());

我应该如何注释这种东西?在@return 中提示@return DomainA|DomainB|DomainC... 等所有域的情况都不好,因为我们有数百个域,而且在功能上期望父P\M\Model 也不好,因为我们想确定它是唯一的DomainA。

谢谢。

【问题讨论】:

标签: php phpstorm phpdoc type-hinting


【解决方案1】:

尝试使用接口而不是基本模型。根据我的经验,有时 PHPStorm 会与这种复杂的类层次结构混淆。在我的程序中,我定义了一个接口并针对它输入提示。这允许 PHPStorm 正确检测类

【讨论】:

  • 但是当我需要基本模型有非抽象方法时呢?然后我应该添加接口但仍扩展基本模型吗?
  • 你可以。您也可以使用接口来创建一种用于开发应用程序的最佳实践,这样不仅可以使 PHPStorm 快乐,还可以形式化类系统的结构。我应该注意我还看到其他开发人员创建空白接口来解决这个问题
【解决方案2】:

如果您在 RepositoryA 类中重新定义 find(),则只需使用 @return DomainA 注释其实现即可。否则,在RepositoryA 类的文档块中将find() 声明为@method,并将DomainA 作为其返回类型。

两种方法都显示如下:

/**
 * @method DomainA find()          <-- use this when the method is inherited 
 *                                     but not redefined in this class
 */
class RepositoryA extends Repository
{
    /**
     * @return DomainA             <-- preferably use this
     */
    public function find()
    {

    }
}

类似的技巧可以用于继承属性,在子类中存储类的对象,这些类扩展了基类中注释中使用的类:

/**
 * @property DomainA $member       <-- it was declared as @var Domain $member
 *                                     in the base class
 */

【讨论】:

    【解决方案3】:

    PSR-5 定义了一个 @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 {}
    

    回复:取自我的SO answer here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多