Search code examples
phpoopphpstorm

Type Hinting abstract class singleton


How would one Type Hint a static singleton-returning method on an abstract class, which returns instances of the extending called classes?

For example, let's look at the following code:

<?php

abstract class Foo {

    /** @return Foo */
    public function init() {
        static $instance;

        if ( is_null($instance) ) {
            $class = get_called_class();
            $instance = new $class();
        }

        return $instance;
    }

}

class Bar extends Foo {

    public $name = "Bar name";

}

class Baz extends Foo {

    public $age = 42;

}

My intention is for tools such as PhpStorm to understand that Bar::init() returns an object of type Bar and that Baz::init() returns an object of type Baz. Thus, for example, objects created from the Baz::init() method would auto-complete the name property but not the age property.

Obviously the current type hint @return Foo is wrong as the method will never return an object instance of an abstract class.


Solution

  • So @return static will work in this case for PHPStorm. It is the easiest option and will provide what you are looking for.

    Optionally you can use the @method annotation against the class although this is very manual and needs to be done for each class. There is another strange thing with this method in PHPStorm where if you navigate to the init() method (ctrl+click or w/e) it will navigate to this annotation first. However this is how that looks:

    /**
     * @method Bar init()
     */
    class Baz extends Foo 
    {
    }
    

    Where optionally as a final resort--and I really don't think you will need it but its here for completeness. Extend the method and add your return annotation as you would a normal method.

    /**
     * @return Baz
     */
    public function init() 
    {
        return parent::init();
    }