在什么条件下PHP 7的自我引用了基类?

dot*_*hen 7 php inheritance php-7

正如在Reddit的LOL PHP子上所指出,PHP 7在引用时可以使用扩展类或基类self,而PHP 5总是引用扩展类.

<?php

class Foo {
    const A = "FooA";
    const B = self::A . self::C;
    const C = "FooC";

}

class Bar extends Foo {
    const A = "BarA";
    const C = "BarC";
}

var_dump(Bar::B);
Run Code Online (Sandbox Code Playgroud)

在线尝试

PHP 5

string(8) "BarABarC"
Run Code Online (Sandbox Code Playgroud)

PHP 7

string(8) "FooABarC"
Run Code Online (Sandbox Code Playgroud)

PHP 7的行为特别令人担忧,因为似乎没有任何简单的规则来知道何时self引用基类或扩展类.在PHP 7中确定哪个类self将引用的规则是什么?

use*_*918 2

self:: 始终引用它所使用的类(请注意,PHP 5 的行为也是错误的。)

这是一个错误7.1.4中修复,适用于类常量的解析self::parent::仅适用于类常量内。

基本上在:

const B = self::A . self::C;
Run Code Online (Sandbox Code Playgroud)

self::C目前仍未知,解决方案被推迟。不幸的是,在最终解决时,正确的范围丢失了。


这个问题也比简单的基础与扩展更加微妙,因为您最终可能会得到来自不同扩展类的值。例如:

https://3v4l.org/cY1I0

class A {
    const selfN = self::N;
    const N = 'A';
}

class B extends A {
    const N = 'B';
}

class C extends A {
    const N = 'C';
}

var_dump(B::selfN); // A

var_dump(C::selfN); // A
Run Code Online (Sandbox Code Playgroud)

在 PHP 7.0.0 到 7.1.3 中,输出:

string(1) "B"
string(1) "B"
Run Code Online (Sandbox Code Playgroud)

不过如果你把它换成:

https://3v4l.org/RltQj

var_dump(C::selfN); // A

var_dump(B::selfN); // A
Run Code Online (Sandbox Code Playgroud)

你会得到:

string(1) "C"
string(1) "C"
Run Code Online (Sandbox Code Playgroud)

为了避免在受影响的版本中出现这种情况,请使用类名称而不是self::类常量定义,例如const selfN = A::N