考虑下面的示例。类A具有private const SOMETHING,但类b具有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的定义,则会引发错误:
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可以解决此问题。
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在应用null合并运算符之前评估b::SOMETHING,根据the documentation:



由于未设置b::SOMETHING,为什么第一个示例无法正常工作,并且基类中的常量需要一致的可见性?

最佳答案

感谢@Devon和@Dormilich的回复。

TL; DR:您不能将null合并运算符(??)与常量一起使用。您必须改为使用defined()

根据the documentation for the null coalescing operator (??):



意思是$x ?? $yisset($x) ? $x : $y的简写。这就是问题所在,因为documentation for isset明确指出:



那就是抛出致命的php错误的原因,我在问题中对此进行了描述。相反,一种解决方案是取消空合并运算符,然后将其替换为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正确指出的那样,privatea::SOMETHING可见性阻止了b类看到它,因此未定义b::SOMETHING。但是,当a::SOMETHING的可见性更改为protected时,类b可以看到它,并且b::SOMETHING引用它。这段代码根本不需要null合并运算符,并且可以只使用static::SOMETHING而无需任何条件:
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 - 为什么PHP的null合并运算符(??)不能在具有不同可见性的类常量上工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50971530/

10-17 02:46