Return 在摘要中输入 "self" PHP class

Return type "self" in abstract PHP class

PHP 7.1

我目前正在尝试制作一个抽象 class 来提供和定义并部分实现其子 classes 的功能。

这里我使用了以下结构:

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;

}

这里PHP好像理解setName($name)return是一个Parent类型的Object,但是PhpStorm提示read()不能在结果,这本来是预期的结果。

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

我不确定这是 PHP 还是 PhpStorm 中的错误,或者更可能的是,我不明白我在做什么...

我已经阅读了 Late static binding 和以下部分讨论这个问题的问题,但我不知道如何解决它:

感谢您的宝贵时间和帮助。


编辑: 如下所示,我正在尝试在子 classes 中实现,例如:

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

这显然不适用于 self return 但(IMO 应该)与 static 一起使用,这是被禁止的。

尝试更改为 return static,static 应该表明您正在 return 扩展 class,这可能会消除错误。

这是猜测,但值得一试。

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

编辑:好的,我认为这不行,您能否提供有关该问题的更多信息?读书的目的是什么?来自数据库?等等?

self总是引用class它的,从不children class es。因此,当 Parent 对 return :self 说时,它期望您创建一个 return 是 Parent 实例的函数。您需要做的是让您的 child class 声明它直接这样做。我们没有声明 child 的 setName 将 return :self(这是 Child 的一个实例),而是声明我们将要 return 我们的 Parent class 直接。 PHP 认为这是完全有效的(Child 毕竟是 Parent 的一个实例)

我们不能在这里使用 :static 因为 static 是 class 定义中的保留字

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

以上代码runs without error

您的代码示例在 PhpStorm 2017.2(目前处于 EAP 阶段)中看起来不错,但在 2017.1.4 中显示警告。

很可能它已被 WI-33991 或其中一张相关票证修复。


您可以随时从此处获取并试用 2017.2 EAP 版本:http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program

它带有自己的 30 天许可证,可以 运行 与您当前的版本并行(IDE-wide 设置存储在单独的文件夹中)。

恕我直言,有一种智能且可靠的接口使用方法。 对于应该由第 3 方使用的库来说甚至是必需的。

所以,我们只是将接口名称设置为一个类型,而不是所有父 类 中的 'self',并继续为子 'self' 使用

<?php
interface EntityInterface 
{
    public function setName(string $name): EntityInterface;
}

abstract class ParentTest implements EntityInterface 
{

    public abstract function read();

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

}

class Child extends ParentTest 
{
    
    private string $name = '';
    
    public function read(): string 
    {
        return $this->name;
    }

    public function setName(string $name): self 
    {
        $this->name = $name;
        return $this;
    }
}

$child = new Child();
echo $child->setName('hello')->read();