我正在使用创建新的堆栈对象
$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替换原则,不允许在此处添加类型提示(子方法必须与父方法兼容),但没有什么可以阻止您在需要时添加if
和throw
。
然而,这种方法的最终结果是,您的代码将(稍微)慢一些,因为每个方法调用都会增加开销。所以,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();
}