PHP 如何为类型提示数据结构编写 phpdoc

PHP how to write a phpdoc for type hinting a data structure

我正在使用

创建新的堆栈对象
$this->postfix = new \splStack;

此堆栈将仅处理 Token 个对象

如何告诉 PHPSTORM pop 命令将返回一个 Token 对象?

我是否必须创建另一个简单地扩展 splStack 的堆栈对象,然后为其编写 phpdoc,或者我应该处理这将是困难的事实并继续前进?

谢谢, 杰森

TL;TR: 处理它。您 可以 添加一个额外的继承层,但是如果所有的好处都是让您可以拥有您想要的文档块,那真的是毫无意义的。最好使用适当的变量名 ($tokenStack),或使用内联注释,如:/** @var Token $token */ 每当您编写 $token = $tokenStack->pop(); 或其他内容时。或者,看到你的堆栈显然是一个 属性,写一个方法从堆栈中弹出,然后调用它 ($this->popToken();).

话虽这么说:如果您想要一个用于实现特定接口的对象的堆栈,那么额外的抽象层可能会有用:

class TraversableStack extends SplStack
{
    public function add($index, $newVal)
    {
        if (!$newVal instanceof Traversable) {
            throw new InvalidArgumentException('TraversableStack only accepts Traversable values');
        }
        return parent::add($index, $newVal);
    }
    /**
     * @return Traversable
     */
    public function pop()
    {
        return parent::pop();
    }
}

并对所有相关方法执行相同的操作。由于 Liskov 替换原则,不允许在此处添加类型提示(子方法 必须 与父方法兼容),但是没有什么可以阻止您添加 if's 和 throw's 在你需要的时候。

不过,这种方法的最终结果是您的代码会(稍微)变慢,因为每个方法调用都会增加开销。所以恕我直言,我只是接受它,并使用内嵌注释来关闭 PhpStorm 关于 methods/properties 不存在。毕竟,像这样的代码并不难读:

$this->tokenStack = new \SplStack;
$this->tokenStack->push($token);
//more code
/** @var Token $lastToken */
$lastToken = $this->tokenStack->pop();

就像我在评论中所说的那样:考虑到您的堆栈已分配给 属性,您可以轻松地创建一个在内部调用 SplStack::pop 的方法,并添加您的 doc-block那里:

/**
 * @return Token
 * @throws \RuntimeException
 */
protected function popToken()
{
    return $this->tokenStack->pop();
}