问题描述
请考虑以下示例.类A具有private const SOMETHING
,但类b具有protected const SOMETHING
.
Consider the example below. Class a has private const SOMETHING
, but class b has protected const SOMETHING
.
class a {
private const SOMETHING = 'This is a!';
public static function outputSomething() {
return static::SOMETHING ?? self::SOMETHING;
}
}
class b extends a {
protected const SOMETHING = 'This is b!';
}
echo (new b())::outputSomething();
输出:
This is b!
但是现在,如果我注释掉类b中SOMETHING
的定义,则会引发错误:
But now if I comment out the definition for SOMETHING
in class b, an error is thrown:
class a {
private const SOMETHING = 'This is a!';
public static function outputSomething() {
return static::SOMETHING ?? self::SOMETHING;
}
}
class b extends a {
//protected const SOMETHING = 'This is b!';
}
echo (new b())::outputSomething();
输出:
Fatal error: Uncaught Error: Cannot access private const b::SOMETHING in {file}.php:7
但是,将A类的可见性从private const SOMETHING
更改为protected const SOMETHING
可以解决此问题.
However, changing the visibility from private const SOMETHING
to protected const SOMETHING
in class a fixes this.
class a {
protected const SOMETHING = 'This is a!';
public static function outputSomething() {
return static::SOMETHING ?? self::SOMETHING;
}
}
class b extends a {
//protected const SOMETHING = 'This is b!';
}
echo (new b())::outputSomething();
现在输出符合预期:
This is a!
我不明白为什么php在应用空合并运算符之前会评估b :: SOMETHING,根据文档:
I don't understand why php is evaluating b::SOMETHING prior to applying the null coalescing operator, which according to the documentation:
由于未设置b :: SOMETHING,为什么第一个示例不起作用,并且基类中的常量需要一致的可见性?
Since b::SOMETHING is not set, why doesn't the first example work and a consistent visibility is required for the constant in the base class?
推荐答案
感谢@Devon和@Dormilich的答复.
Thanks to @Devon and @Dormilich for their responses.
TL; DR:您不能将空合并运算符(??
)与常量一起使用.您必须改为使用defined()
.
TL;DR: You can't use the null coalescing operator (??
) with constants. You have to use defined()
instead.
表示$x ?? $y
是isset($x) ? $x : $y
的简写.这就是问题所在,因为 isset文档明确指出:
Meaning that $x ?? $y
is shorthand for isset($x) ? $x : $y
. And this is where the problem lies, because the documentation for isset explicitly states:
这就是引发我在问题中描述的致命php错误的原因.相反,一种解决方案是取消空合并运算符,并将其替换为defined()
:
That's what throws the fatal php error I describe in the question. Instead, a solution would be to do away with the null coalescing operator and replace it with defined()
:
class a {
private const SOMETHING = 'This is a!';
public static function outputSomething() {
return defined('static::SOMETHING') ? static::SOMETHING : self::SOMETHING;
}
}
class b extends a {
//protected const SOMETHING = 'This is b!';
}
echo (new b())::outputSomething();
第二种解决方案是首先更改代码的工作方式.正如@Devon正确指出的那样,a::SOMETHING
的private
可见性阻止了b类看到它,因此未定义b::SOMETHING
.但是,当a::SOMETHING
的可见性更改为protected
时,类b可以看到它,而b::SOMETHING
引用它.这段代码根本不需要null合并运算符,并且可以直接使用static::SOMETHING
,而无需任何条件:
A second solution is to change how the code works in the first place. As @Devon correctly points out, the private
visibility of a::SOMETHING
prevents class b from seeing it, so b::SOMETHING
is not defined. However, when the visibility of a::SOMETHING
is changed to protected
, class b can see it and b::SOMETHING
references it. This code doesn't need the null coalescing operator at all, and can just use static::SOMETHING
without any conditional:
class a {
protected const SOMETHING = 'This is a!';
public static function outputSomething() {
return static::SOMETHING;
}
}
class b extends a {
//protected const SOMETHING = 'This is b!';
}
echo (new b())::outputSomething();
这篇关于为什么PHP的null合并运算符(??)不能在具有不同可见性的类常量上工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!