在接口中实现类型提示 'parent' 会引发错误

Implement type hinting 'parent' in interface throws an error

可以在界面中输入提示 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);
}

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

// 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)

  1. 所以如果I1不是I2的parent,那是谁呢?

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

PHP 7.4 will thrown new deprecation error message 如果 parent pseudo-type 用于没有父类型的地方。接口就是其中一个例子。

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

Deprecated: Cannot use "parent" when current class scope has no parent in /in/tOSug on line 8

Fatal error: Could not check compatibility between B::instanceOfParent(I1 $object) and I2::instanceOfParent(parent $object), because class parent is not available in /in/tOSug on line 22

这表明问题出在哪里。界面中不能使用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

有趣的是 parent 的类型提示在 Type declarations

下的 PHP 手册中没有记录

解释为什么代码的行为不像您预期​​的那样。

关键字 parent 总是引用父 class,或者换句话说,您从中扩展的 class。在您的示例中, B class 没有父级。它只实现了一个接口。

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

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

这段代码会抛出错误:

Fatal error: Uncaught Error: Cannot use "parent" when current class scope has no parent

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

interface I1 {
    public function amIanOrphan();
}

interface I2 extends I1 {
}

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

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