简体   繁体   中英

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

I am creating new stack object with

$this->postfix = new \splStack;

This stack will only handle Token Objects

How can I tell PHPSTORM that the pop command will be returning a Token Object?

Will I have to create another stack object that simply extends splStack and then write phpdocs for it or should I just deal with the fact that It will be difficult and move on?

Thanks, Jason

TL;TR: deal with it. You could add an extra layer of inheritance, but if all that is good for is so you can have the docblock you want in place, that's really rather pointless. It'd be better for you to use a proper variable name ( $tokenStack ), or use inline comments like: /** @var Token $token */ whenever you write $token = $tokenStack->pop(); or something. Alternatively, seeing as your stack is clearly a property, write a method to pop from the stack, and call that instead ( $this->popToken(); ).

That being said: and additional layer of abstraction might be useful if you want a stack for objects that implement a particular interface:

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();
    }
}

And do the same for all relevant methods. Because of the Liskov substitution principle, it is not allowed to add type hints here (child methods must be compatible with the parent), but there's nothing to prevent you from adding the if 's and throw 's when you need them.

The end result of this approach, though, is that your code will be (slightly) slower, because each method call adds overhead. So IMHO, I'd just go with it, and use inline comments to shut PhpStorm up about methods/properties not existing. After all, code like this isn't that hard to read:

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

And like I said in my comment: considering your stack is assigned to a property anyway, you could easily create a method that calls SplStack::pop internally, and add your doc-block there:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM