在接口中实现类型提示 '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)
所以如果I1
不是I2
的parent,那是谁呢?
这是一个已知错误吗,可以在界面中键入提示 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 没有父级,并且相同的逻辑适用于类型提示。
可以在界面中输入提示 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)
所以如果
I1
不是I2
的parent,那是谁呢?这是一个已知错误吗,可以在界面中键入提示
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
解释为什么代码的行为不像您预期的那样。
关键字 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 没有父级,并且相同的逻辑适用于类型提示。