Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/247.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从表达式创建PHP类常量的最佳解决方案?_Php_Class_Constants - Fatal编程技术网

从表达式创建PHP类常量的最佳解决方案?

从表达式创建PHP类常量的最佳解决方案?,php,class,constants,Php,Class,Constants,我希望能够做到这样: 类圆{ 常数半径到周长=M_PI*2;//不允许 私有$半径; 公共功能构造($radius){ $this->radius=$radius; } ... 公共函数{ 返回$this->radius*self::radius\u TO\u圆周; } } 但是我不能从这样的表达式创建一个表达式: 值必须是常量表达式,而不是(例如)变量、属性、数学运算的结果或函数调用 所以我的问题是:对于PHP的这种局限性,最好的解决方法是什么?我知道以下解决方法,但还有其他更好的吗?

我希望能够做到这样:

类圆{
常数半径到周长=M_PI*2;//不允许
私有$半径;
公共功能构造($radius){
$this->radius=$radius;
}
...
公共函数{
返回$this->radius*self::radius\u TO\u圆周;
}
}
但是我不能从这样的表达式创建一个表达式:

值必须是常量表达式,而不是(例如)变量、属性、数学运算的结果或函数调用


所以我的问题是:对于PHP的这种局限性,最好的解决方法是什么?我知道以下解决方法,但还有其他更好的吗?

1.创建属性
类圆{
私有静态$半径到周长;
私有$半径;
公共功能构造($radius){
$this->radius=$radius;
$this->RADIUS_TO_percentral=M_PI*2;
}
...
公共函数{
返回$this->radius*$this->radius\u TO\u圆周;
}
}
我不喜欢这样,因为
$RADIUS\u TO\u percentral
的值可以更改,所以它实际上不是一个“常数”。

2.使用
define()
define('RAD_TO_circu',M_PI*2);
班级圈子{
常数半径到周长=半径到周长;
...
公共函数{
返回$this->radius*self::radius\u TO\u圆周;
}
}
这更好,因为该值确实是常量,但缺点是,
RAD\u-TO\u-circu
已全局定义

离题

我不明白这是怎么回事。(编辑:我已经测试过了,它确实有效。)根据:

const
修饰符创建一个编译时常量,因此编译器将用该常量的值替换该常量的所有用法。相反,
define
创建一个运行时常量,该常量在运行时之前不会设置。这就是为什么
define
常量可以指定表达式值,而
const
需要编译时已知的常量值的原因

“使用
const
关键字定义的常数…在编译时定义”的手册

在3年前的一篇文章中,PHP团队的一名成员写道:

对于类常量,我们在编译时需要一个常量值,不能对表达式求值
define()
是一个常规函数,在运行时进行计算,因此可以包含任何形式的值

但是在我上面的例子中,
RAD\u TO\u-circu
的值在编译时是未知的。那么编译器对
半径到周长的值是什么呢

我猜编译器会为
半径到周长
的值创建某种占位符,在运行时,该占位符会被替换为
半径到周长
的值。这个占位符可能是一种?如果是这样,也许应该避免这种技术?手册:“可以将常量定义为资源,但应该避免,因为它可能导致意外结果。”

3.创建一个方法
类圆{
...
专用静态函数半径到周长(){
返回M_PI*2;
}
公共函数{
返回$this->radius*$this->radius_TO_percentral();
}
}
这是我知道的我最喜欢的解决方法。该值为常量,不影响全局空间


还有其他更好的解决方法吗?

如果您同意使用标准变量而不是常量关键字:

class Foo {

    public $CONST_A; // = calculation A // To let people quickly see the value.
    public $CONST_B; // = calculation B 

    public static function initClass() {
        self::$CONST_A = /* calculation A */;
        self::$CONST_B = /* calculation B */;
    }
}

Foo::initClass();

initClass()
仅在需要类文件时执行一次。

我建议使用这种方法:

class Circle {

    ...

    private function RADIUS_TO_CIRCUMFERENCE() {
        static $RADIUS_TO_CIRCUMFERENCE;

        if ( null === $RADIUS_TO_CIRCUMFERENCE )
            $RADIUS_TO_CIRCUMFERENCE = M_PI * 2;

        return $RADIUS_TO_CIRCUMFERENCE;
    }

    public function getCircumference() {
        return $this->radius * $this->RADIUS_TO_CIRCUMFERENCE();
    }
}

目标是对所有类实体只计算一次,如实常量。

从PHP 5.6开始,您可以使用,因此这将起作用:

const RADIUS_TO_CIRCUMFERENCE = M_PI * 2;
我遇到此线程是因为我的环境配置不正确(意外设置为PHP5.4),所以不要忘记检查您的PHP版本。

在我的情况下

我安装的php版本是7.1,但在我的IDE(PhpStorm)设置中选择了php版本5.4。一旦我更改了php版本,问题就消失了


phpstormsettings->PHP并更改PHP语言级别和CLI解释器PHP版本。

Hmmm忘了我的答案吧,这太愚蠢了。x) 无法修改常量值,这就是它的用途…顺便说一句,解决方案2)不起作用。define()是运行时,而const是“编译”时(即之前完成的)。为什么要担心全局范围
M_PI
也是全局的。另外,问问自己是否真的需要这个常量。返回
$this->radius*M_PI*2
可能更具可读性。让PHP担心任何优化。@Virus721我知道
const
是在
define()
之前完成的–请参阅我的“离题”。解决方案#2不应该有效,但它确实有效(我已经测试过了),我想知道它为什么有效。谢谢你的回答,但不幸的是它对我没有帮助。首先,属性
$CONST_A
$CONST_B
必须是
公共静态
,代码才能工作。您的答案与我的解决方案#1存在相同的问题(属性的值可以更改,因此这不是创建“常量”的好方法)。此外,由于属性是
public
,任何人都可以通过执行类似
Foo::$CONST_A=10。这在PHP5.6之后就不需要了