为什么PHP的null合并运算符(??)不能在具有不同可见性的类常量上工作? [英] Why doesn't PHP's null coalescing operator (??) work on class constants with different visibilities?

查看:73
本文介绍了为什么PHP的null合并运算符(??)不能在具有不同可见性的类常量上工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下示例.类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:

已添加空合并运算符(??)作为语法糖 对于需要结合使用三元数的常见情况 isset().如果它存在且不为NULL,则返回其第一个操作数;否则,返回第一个操作数. 否则,它将返回其第二个操作数.

The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.

由于未设置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.

根据空合并运算符(??)的文档:

已添加空合并运算符(??)作为语法糖 对于需要结合使用三元数的常见情况 isset().如果存在且不为NULL,则返回其第一个操作数;否则,返回第一个操作数. 否则,它将返回其第二个操作数.

The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.

表示$x ?? $yisset($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:

警告:isset()仅在传递其他任何内容时才与变量一起使用 将导致解析错误.用于检查是否设置了常量 define()函数.

Warning: isset() only works with variables as passing anything else will result in a parse error. For checking if constants are set use the defined() function.

这就是引发我在问题中描述的致命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::SOMETHINGprivate可见性阻止了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合并运算符(??)不能在具有不同可见性的类常量上工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆