1

base classes:

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

class B extends A
{
    public function methodB() { echo __FUNCTION__.'<br>'; }
}

so far so good. A factory which can create any of them:

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

phpdoc is right, since it say "return something comes from A". Now the tricky part comes:

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

this will run for sure, but check for the methodB() calling. IDE wont autocomplete with this method. How to tell that var is now B, not A with phpDoc?

2
  • 1
    Not clear how @return A is actually correct, when you're returning B? PHPStorm (at least) would properly autocomplete if you had @var B on your protected $var variable... (tested and proven in PHPStorm. Lints properly, and auto-completes properly with this one change). Commented Oct 27, 2017 at 22:36
  • 1
    @cale_b It's correct since A is part of the inheritance chain of B. The phpdoc only says that the method will return a class conforming to the definition of class A. B does that (since it extends A). Which is also the reason why PHPStorm won't autocomplete - since you can't assume that methodB exists from the current hints. Commented Oct 27, 2017 at 22:57

1 Answer 1

3

You can override inherited properties for PHPStorm's autocompletion:

/**
 * @property B $var
 */
class OwnClassB extends OwnClass
{
    //...
}

However, I personally think you're trying to solve the wrong problem. If you have a Factory class that returns either A or B, you shouldn't type hint the return value to A. Instead, you should provide both:

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

Both options inform PHPStorm enough to let it show you both methods as autocomplete options, but the latter is accurate in terms of what the code actually does (well, not in this example, but given the function name I guess that's what your real-world implementation does).

Sign up to request clarification or add additional context in comments.

2 Comments

hinting both A and B is wrong, since it may return with a future C, D .... classes
Ok, in that case it would be counterproductive to hint A|B|C|D because you'd probably end up with a lot of autocomplete options that do not actually apply. Then the first option is probably a better choice.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.