How to indicate in php 7.1 that the return type is the current child type?

Viewed 1276

I have

abstract class A{
  public static function getSingle($where = []) {
    $classname = get_called_class();

    $record =     static::turnTheWhereIntoArecordFromDB($where);
    $model = new  $classname($record);
    return $model;
  }
}

class B extends A{

}


$x = B::getSingle();

$x has no type hinting... I like type hinting, so I want type hinting for B, not for A

How to enable type hinting directly for $x?

what I thought is something like

 public function getSingle($where = []) : ?get_called_class()

This obviously doesn't work

Is there something that does?

4 Answers

For the example you present, why do you need to have a factory method? You are creating a new instance from the constructor, why don't you just $x = new B($record)!

UPDATED ABOVE


abstract class A
{
    /**
     * @param array $where
     * @return static
     */
    public static function getSingle($where = [])
    {
        $classname = get_called_class();

        $model = new  $classname($record);
        return $model;
    }
}

@return static will type hinting its child class. Also I changed your function to static function, it is typical factory pattern.

I know that you specify PHP 7.1, but starting with PHP 8 (to be released on November 2020) this will be possible with the addition of the static return type hint.

The RFC was approved unanimously, 54-0.

This means you'll be able to do:

class Foo

   public static function build(): static
   {
        return new static();
   }
}

class Bar extends Foo {}

Additionally, no need to muck around with $classname = get_called_class(); new $classname();. You can simply do new static(), which is neater and has the same result.

And Bar::build() is type-hinted to indicate that it returns Bar and not Foo by virtue of late static binding.

Let the abstract class implement an interface and type hint that interface. The child does not have to implement the interface explicitly.

abstract class A implements BarInterface
  {
    public function foo (): BarInterface
      {    
        return new static;
      }
  }
Related