我希望能够做到这样的事情:
class Circle {
const RADIUS_TO_CIRCUMFERENCE = M_PI * 2; // Not allowed
private $radius;
public function __construct( $radius ) {
$this->radius = $radius;
}
...
public function getCircumference() {
return $this->radius * self::RADIUS_TO_CIRCUMFERENCE;
}
}
但我不能从像这样的表达式创建class constant:
值必须是常量表达式,而不是(例如)变量,属性,数学运算的结果或函数调用。
所以我的问题是:这种PHP限制的最佳解决方法是什么?我知道以下变通方法,但还有其他更好的方法吗?
class Circle {
private static $RADIUS_TO_CIRCUMFERENCE;
private $radius;
public function __construct( $radius ) {
$this->radius = $radius;
$this->RADIUS_TO_CIRCUMFERENCE = M_PI * 2;
}
...
public function getCircumference() {
return $this->radius * $this->RADIUS_TO_CIRCUMFERENCE;
}
}
我不喜欢这样,因为$RADIUS_TO_CIRCUMFERENCE
的值可以改变,所以它不是真正的“常数”。
define()
define( 'RAD_TO_CIRCUM', M_PI * 2 );
class Circle {
const RADIUS_TO_CIRCUMFERENCE = RAD_TO_CIRCUM;
...
public function getCircumference() {
return $this->radius * self::RADIUS_TO_CIRCUMFERENCE;
}
}
这样做更好,因为该值确实是恒定的,但缺点是RAD_TO_CIRCUM
已全局定义。
一个题外话题
我不明白这是如何工作的。 (编辑:我已对其进行了测试,但确实有效。)根据Handbook of PHP Syntax:
const
修饰符创建编译时常量,因此编译器将使用其值替换常量的所有用法。相反,define
创建一个运行时常量,直到运行时才设置。这就是为什么define
常量可以赋予表达值的原因,而const
需要在编译时已知的常量值。
使用const
关键字定义的常量的手册confirms在编译时定义。“
在3年前的this bug report中,PHP团队的一名成员写道:
对于类常量,我们在编译时需要一个常量值,不能计算表达式。
define()
是一个常规函数,在运行时进行评估,因此可以包含任何形式的任何值。
但是在上面的例子中,RAD_TO_CIRCUM
的值在编译时是未知的。那么编译器为RADIUS_TO_CIRCUMFERENCE
的值设置了什么?
我猜测编译器会为RADIUS_TO_CIRCUMFERENCE
的值创建某种占位符,并且在运行时,该占位符将替换为RAD_TO_CIRCUM
的值。这个占位符可能是resource的一种吗?如果是这样,也许应该避免这种技术?手册says:“可以将常量定义为资源,但应该避免,因为它可能会导致意外结果。”
class Circle {
...
private static function RADIUS_TO_CIRCUMFERENCE() {
return M_PI * 2;
}
public function getCircumference() {
return $this->radius * $this->RADIUS_TO_CIRCUMFERENCE();
}
}
这是我最喜欢的解决方法,我知道。该值是常量,不会影响全局空间。
还有其他解决方法更好吗?
答案 0 :(得分:13)
从PHP 5.6开始,您可以使用math expressions in PHP constants,这样就可以了:
const RADIUS_TO_CIRCUMFERENCE = M_PI * 2;
我遇到了这个帖子,因为我的环境没有正确配置(偶然设置为PHP 5.4),所以不要忘记查看你的PHP版本。
答案 1 :(得分:2)
我会推荐这种方法:
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();
}
}
目标是对所有类实体只计算一次,如实常数。
答案 2 :(得分:0)
如果您同意使用标准变量而不是const关键字:
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()
只需要一次,当需要类文件时。
答案 3 :(得分:0)
就我而言
我安装的php版本是7.1,但是在我的IDE(PhpStorm)设置中选择了php版本5.4。一旦我更改了php版本,问题就消失了。
PhpStorm设置-> PHP,并更改PHP语言级别和CLI解释器php版本。