变量的Phpdoc“;“铸造”吗;?

变量的Phpdoc“;“铸造”吗;?,php,phpdoc,Php,Phpdoc,基类: abstract class A { public function methodA() { echo __FUNCTION__.'<br>'; } } class B extends A { public function methodB() { echo __FUNCTION__.'<br>'; } } phpdoc是正确的,因为它说“返回来自A”的内容。 现在棘手的部分来了: class OwnClass { /** *

基类:

abstract class A
{
    public function methodA() { echo __FUNCTION__.'<br>'; }
}

class B extends A
{
    public function methodB() { echo __FUNCTION__.'<br>'; }
}
phpdoc是正确的,因为它说“返回来自
A
”的内容。 现在棘手的部分来了:

class OwnClass
{
    /**
     * @var A
     */
    protected $var;

    public function __construct()
    {
        $this->var = \Factory::createAorB();
    }
}

class OwnClassB extends OwnClass
{
    public function callMe()
    {
        $this->var->methodA();
        $this->var->methodB(); // this will also run, but IDE wont autocomplete with this method
    }
}

(new OwnClassB())->callMe();

这肯定会运行,但要检查
methodB()
调用。IDE不会使用此方法自动完成。如何使用phpDoc判断var现在是
B
,而不是
A

您可以覆盖PHPStorm自动完成的继承属性:

/**
 * @property B $var
 */
class OwnClassB extends OwnClass
{
    //...
}
然而,我个人认为你试图解决错误的问题。如果您有一个返回
a
B
的工厂类,则不应向
a
键入返回值。相反,您应该同时提供:

class Factory
{
    /**
     * @return A|B
     */
    public static function createAorB()
    {
        return new B();
    }
}

这两个选项都足以通知PHPStorm,让它以自动完成选项的形式向您显示这两种方法,但后者在代码实际执行的功能方面是准确的(好吧,在本例中不是这样,但给定函数名,我想这就是您的实际实现所做的)。

不清楚
@return A
实际上是如何正确的,当您返回
B
时?如果在
受保护的$var
变量上有
@var B
,则PHPStorm(至少)将正确地自动完成。。。(在PHPStorm.Lints中正确测试和验证,并通过这一更改正确自动完成)。@cale_b这是正确的,因为
A
b
继承链的一部分。phpdoc只说该方法将返回一个符合类a定义的类。B会这样做(因为它扩展了a)。这也是PHPStorm无法自动完成的原因-因为您不能假设当前提示中存在
methodB
。同时提示A和B是错误的,因为它可能返回未来的C、D。。。。classesOk,在这种情况下,提示
A | B | C | D
会适得其反,因为您可能最终会得到许多实际上并不适用的自动完成选项。那么第一种选择可能是更好的选择。
class Factory
{
    /**
     * @return A|B
     */
    public static function createAorB()
    {
        return new B();
    }
}