Return type “self” in abstract PHP class

ぐ巨炮叔叔 提交于 2019-12-23 10:36:07

问题


PHP 7.1

I'm currently trying to make an abstract class to provide and define and partially implement functionality of its' child classes.

Here I use the following construct:

abstract class Parent {

    public static function fromDB(string $name = '') {
        $instance = new static();
        if (!empty($name)) {
            $instance->setName($name)->read();
        }
        return $instance;
    }

    public abstract function read();

    public abstract function setName(string $name): self;

}

Here PHP seems to understand that setName($name) returns a Object with type Parent, but PhpStorm indicates that read() can not be called on the result, which would have been the expected result.

Error Message: Referenced Method is not found in subject class.

I'm not sure if this is a bug in PHP or PhpStorm, or, much more likely, me not understanding what I'm doing...

I've read up on Late static binding and the following questions which partially talk about this problem, but I couldn't figure out how to fix it:

  • Question 1
  • Question 2
  • Late Static Binding Doc

Thank you for your time and help.


EDIT: As hinted below, I'm trying to implement in child classes like:

public function setName(string $name = null): user {...}

which obviously doesn't work with self return but (IMO should) with static, which is forbidden.


回答1:


Your code sample looks fine in PhpStorm 2017.2 (currently in EAP stage) but shows warning in 2017.1.4.

Quite possibly it was fixed by WI-33991 or one of the related tickets.


You may get & try the 2017.2 EAP build at any time from here: http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program

It comes with own 30-days license and can run in parallel to your current version (IDE-wide settings are stored in separate folders).




回答2:


self will always refer to the class its in, never children classes. So when Parent says to return :self, it's expecting you to create a function that returns an instance of Parent. What you need to do is have your child class declare that it's doing that directly. Instead of declaring the child's setName will return :self (which is an instance of Child), we declare we're going to return our Parent class directly. PHP sees this as perfectly valid (Child is an instance of Parent after all)

We cannot use :static here because static is a reserved word in the class definitions

abstract class ParentTest {

    public static function fromDB(string $name = '') {
        $instance = new static();
        if (!empty($name)) {
            $instance->setName($name)->read();
        }
        return $instance;
    }

    public abstract function read();

    public abstract function setName(string $name): self;

}

class Child extends ParentTest {
    public function read() {

    }

    public function setName(string $name) :ParentTest {
        return $this;
    }
}

$child = new Child();

The above code runs without error




回答3:


Try change to return static, static should indiciating you are returning the extending class, which may remove the error.

This is guess work but it's worth a shot.

public abstract function setName(string $name): static;

EDIT: Ok i dont think that will do, can you provide more information on the question? What is the purpose of read? fromDb? etc?



来源:https://stackoverflow.com/questions/44803353/return-type-self-in-abstract-php-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!