在抽象PHP类中返回类型“self”

7y4bm7vi  于 2023-01-04  发布在  PHP
关注(0)|答案(4)|浏览(124)

为了使抽象类部分实现其子类的功能,并在实现所需的子类上强制一个契约,我使用了以下构造:

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)返回一个Parent类型的Object,但是PhpStorm指出不能在结果上调用read(),而这本来是预期的结果。
错误信息:在主题类中未找到引用的方法。
我不明白为什么会发生这种情况,甚至怀疑PHP或PhpStorm中有bug。
我已经阅读了后期静态绑定和以下部分讨论这个问题的问题,但我不知道如何解决它:

感谢您的时间和帮助。
我尝试在子类中实现setName,这样可以清楚地看到返回的Object的类型是子类的类型:

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

它不适用于self返回类型,并且static是禁用的。

8dtrkrch

8dtrkrch1#

self总是引用它所在的类,从不引用子类。因此,当Parent要求返回:self时,它希望你创建一个返回Parent示例的函数。你需要做的是让你的子类声明它直接这样做。s setName将返回:selfChild的示例),我们声明将直接返回Parent类。PHP认为这是完全有效的(毕竟ChildParent的示例)
这里不能使用:static,因为static是类定义中的保留字

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

igetnqfo

igetnqfo2#

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

很可能是WI-33991或相关票证之一修复的。
您可以随时从此处获取并试用2017.2 EAP版本:http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program
它有自己的30天许可证,可以并行运行您的当前版本(IDE范围的设置存储在单独的文件夹)。

pwuypxnk

pwuypxnk3#

恕我直言,有一个智能和坚实的方法来使用接口。它甚至是需要的库应该使用的第三方。
因此,我们只是在所有父类中将接口名称设置为一个类型,而不是“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();
vlju58qv

vlju58qv4#

尝试更改以返回static,static should,这表明您正在返回扩展类,这可能会删 debugging 误。
这是猜测的工作,但值得一试。

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

编辑:好吧,我想这是不行的,你能提供更多的信息吗?什么是阅读的目的?从Db?等?

相关问题