我希望能够做这样的事情:
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;
}
}
但是我不能从这样的表达式中创建一个类常量:
该值必须是常量表达式,而不是(例如)变量、属性、数学运算的结果或函数调用。
所以我的问题是:对于 PHP 的这种限制,最好的解决方法是什么?我知道以下解决方法,但是还有其他更好的方法吗?
1.创建属性
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
可以改变,所以它不是真正的“常数”。
2.使用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
已全局定义。
题外话
我不明白这是怎么回事。(编辑:我已经测试过了,它确实有效。)根据PHP 语法手册:
const
修饰符创建一个编译时常量,因此编译器将用它的值替换该常量的所有用法。相反,define
创建一个运行时常量,直到运行时才设置。这就是为什么define
可以为常量分配表达式值,而const
需要在编译时已知的常量值的原因。
该手册确认“使用关键字定义的常量const
...是在编译时定义的”。
在3 年前的这个错误报告中,PHP 团队的一名成员写道:
对于类常量,我们在编译时需要一个常量值并且不能评估表达式。
define()
是一个常规函数,在运行时计算,因此可以包含任何形式的任何值。
但在我上面的例子中, 的值RAD_TO_CIRCUM
在编译时是未知的。那么编译器为 的值添加了RADIUS_TO_CIRCUMFERENCE
什么?
我猜测编译器为 的值创建了某种占位符RADIUS_TO_CIRCUMFERENCE
,并且在运行时,该占位符被替换为 的值RAD_TO_CIRCUM
。这个占位符可能是一种资源吗?如果是这样,也许应该避免这种技术?手册说:“可以将常量定义为资源,但应该避免,因为它会导致意外结果。”
3.创建方法
class Circle {
...
private static function RADIUS_TO_CIRCUMFERENCE() {
return M_PI * 2;
}
public function getCircumference() {
return $this->radius * $this->RADIUS_TO_CIRCUMFERENCE();
}
}
这是我知道的我最喜欢的解决方法。该值是常数,不影响全局空间。
还有其他更好的解决方法吗?