PHP如何编写用于类型提示数据结构的phpdoc


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

我正在使用创建新的堆栈对象

$this->postfix = new 'splStack;

此堆栈将仅处理Token对象

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

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

谢谢,Jason

TL;TR:处理它。你可以添加一层额外的继承,但如果这一切都是好的,那么你就可以拥有你想要的文档块,那真的很没有意义。最好使用合适的变量名($tokenStack),或者在编写$token = $tokenStack->pop();或其他内容时使用内联注释,如:/** @var Token $token */。或者,考虑到堆栈显然是一个属性,编写一个方法从堆栈中弹出,并调用它($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替换原则,不允许在此处添加类型提示(子方法必须与父方法兼容),但没有什么可以阻止您在需要时添加ifthrow

然而,这种方法的最终结果是,您的代码将(稍微)慢一些,因为每个方法调用都会增加开销。所以,IMHO,我会继续使用它,并使用内联注释来关闭PhpStorm关于不存在的方法/属性。毕竟,像这样的代码并不难阅读:

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

正如我在评论中所说:考虑到你的堆栈无论如何都被分配给了一个属性,你可以很容易地在内部创建一个调用SplStack::pop的方法,并在那里添加你的文档块:

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