在接口中实现类型提示“父级”会引发错误

Posted

技术标签:

【中文标题】在接口中实现类型提示“父级”会引发错误【英文标题】:Implement type hinting 'parent' in interface throws an error 【发布时间】:2019-11-12 09:30:55 【问题描述】:

可以在界面中输入提示self

interface I 
    public function instanceOfSelf(self $object);


class A implements I 
    private function printBool(bool $b) 
        echo ($b ? 'true' : 'false') . "\n";
    

    public function instanceOfSelf(I $object) 
        $this->printBool($object instanceof I);
                            


$a = new A;
$a->instanceOfSelf($a); // true

也可以在界面中输入提示parent,这意味着下面的代码不会产生错误:

interface I1 

interface I2 extends I1 
    public function instanceOfSelf(self $object);

    public function instanceOfParent(parent $object);

但是,当根据I2::instanceOfParent 提示I1 时会抛出错误:

// Duplication for completion...
interface I1 
interface I2 extends I1 
    public function instanceOfSelf(self $object);

    public function instanceOfParent(parent $object);


class A implements I1 

class B implements I2 
    private function printBool(bool $b) 
        echo ($b ? 'true' : 'false') . "\n";
    

    public function instanceOfSelf(I2 $object) 
        $this->printBool($object instanceof I2);
    

    public function instanceOfParent(I1 $object) 
        $this->printBool($object instanceof I1);
                            


$a = new A;
$b = new B;

$b->instanceOfSelf($b);   // true
$b->instanceOfParent($a); // true
$b->instanceOfParent($b); // true

这会产生以下错误(php 5.6.30、7.3.3、7.4.0):

Fatal error: Declaration of B::instanceOfParent(I1 $object) must be compatible with I2::instanceOfParent(parent $object)

    那么如果I1 不是I2 的父级,那么谁是?

    这是一个已知的错误,可以在界面中键入提示parent 而无法实现此功能?

【问题讨论】:

【参考方案1】:

PHP 7.4 will thrown new deprecation error message 如果在没有父类型的地方使用了parent 伪类型。接口就是其中一个例子。

When I execute your code I get 2 errors in PHP 7.4:

不推荐使用:当当前类范围在第 8 行的 /in/tOSug 中没有父级时,不能使用“父级”

致命错误:无法检查 B::instanceOfParent(I1 $object) 和 I2::instanceOfParent(parent $object) 之间的兼容性,因为第 22 行的 /in/tOSug 中没有类父级

这表明问题出在哪里。您不能在界面中使用parent。 您可以通过将parent 替换为接口的实际名称来解决此问题:

// Duplication for completion...
interface I1 
interface I2 extends I1 
    public function instanceOfSelf(self $object);

    public function instanceOfParent(I1 $object);


class A implements I1 

class B implements I2 
    private function printBool(bool $b) 
        echo ($b ? 'true' : 'false') . "\n";
    

    public function instanceOfSelf(I2 $object) 
        $this->printBool($object instanceof I2);
    

    public function instanceOfParent(I1 $object) 
        $this->printBool($object instanceof I1);
                            


$a = new A;
$b = new B;

$b->instanceOfSelf($b);   // true
$b->instanceOfParent($a); // true
$b->instanceOfParent($b); // true

在Type declarations 下的 PHP 手册中没有记录使用 parent 的足够有趣的类型提示

解释为什么代码的行为不符合您的预期。

关键字parent 始终指代父类,或者换句话说,您所扩展的类。在您的示例中,B 类没有父级。它只实现了一个接口。

class B  
    public function amIanOrphan() 
        var_dump(parent::class);
                 


$b = new B; 
$b->amIanOrphan();

这段代码会报错:

致命错误:未捕获的错误:当前类范围没有父级时无法使用“父级”

接口本身不是类。接口只告诉你类有哪些方法。 这段代码和上面一模一样:

interface I1 
    public function amIanOrphan();


interface I2 extends I1 


class B implements I2 
    public function amIanOrphan() 
        var_dump(parent::class);
    

接口从另一个接口扩展而来,但类本身仍然没有父类。上面的代码仍然会抛出错误,因为 B 没有父级,同样的逻辑也适用于类型提示。

【讨论】:

谢谢,我没有收到“已弃用”警告,因为我使用了 wandbox。

以上是关于在接口中实现类型提示“父级”会引发错误的主要内容,如果未能解决你的问题,请参考以下文章

“/”应用程序中的服务器错误。引发类型为“System.OutOfMemoryException”的异常。

浪潮GS7提示类型初始值设定项引发异常,该怎么解决?

接口调用过于频繁会引发超时错误吗

在 python 中使用 cppyy 时,指针变量引发错误为未知类型

为啥为 __eq__ 定义参数类型会引发 MyPy 类型错误?

为啥numpy在尝试预测回归时会引发异常错误:“ufunc'add'没有包含具有签名匹配类型的循环”?