14

PHP 7.1

我目前正在尝试创建一个抽象类来提供、定义和部分实现其子类的功能。

在这里,我使用以下构造:

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)返回一个带有 type 的 Object Parent,但是 PhpStorm 表示read()不能在结果上调用,这本来是预期的结果。

错误消息:在主题类中找不到引用的方法。

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

我已经阅读了后期静态绑定和以下部分讨论这个问题的问题,但我不知道如何解决它:

感谢您的时间和帮助。


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

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

这显然不适用于selfreturn 但(IMO 应该) with static,这是被禁止的。

4

4 回答 4

6

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

在此处输入图像描述

很可能它是由WI-33991或相关票证之一修复的。


您可以随时从这里获取并尝试 2017.2 EAP 构建:http: //confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program

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

于 2017-06-28T15:27:28.857 回答
6

self始终指代其所在的类,而不是儿童类。所以当Parent说返回时:self,它期望你创建一个返回一个实例的函数Parent。您需要做的是让您的子类声明它直接这样做。我们没有声明孩子的setNamewill return :self(它是 的一个实例Child),而是声明我们将Parent直接返回我们的类。PHP 认为这是完全有效的(毕竟Child是一个实例)Parent

我们不能: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();

上面的代码运行没有错误

于 2017-06-28T13:13:59.903 回答
1

恕我直言,有一种智能且可靠的方法来使用界面。甚至应该由第 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();
于 2020-11-25T11:56:38.050 回答
-3

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

这是猜测工作,但值得一试。

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

编辑:好的,我认为这不会,你能提供更多关于这个问题的信息吗?读书的目的是什么?来自数据库?ETC?

于 2017-06-28T13:07:02.030 回答