【发布时间】:2011-10-31 23:48:38
【问题描述】:
我可以在类构造函数中定义一个类常量吗?
(基于某些条件)
【问题讨论】:
我可以在类构造函数中定义一个类常量吗?
(基于某些条件)
【问题讨论】:
这与类常量的想法背道而驰——它们不应该依赖于特定的实例。您应该改用变量。
但是,如果您坚持这样做,并且非常冒险并且可以安装 PHP 扩展,您可以查看允许在运行时修改类及其常量的 runkit 扩展。请参阅此文档:http://www.php.net/manual/en/function.runkit-constant-add.php
【讨论】:
static final 的 php 等效项,但不幸的是 php 中的常量有点不同。
我不认为你可以。
这也没有意义 - 类常量可以在静态上下文中使用,其中首先没有构造函数。
您必须改用变量 - 这就是它们的用途。
【讨论】:
【讨论】:
就标准实例构造函数而言,没有办法做到这一点,正如其他人指出的那样,这没有意义。这些构造函数在它们被创建时被每个创建的对象实例调用。无法保证在某些代码尝试访问该常量之前会调用此构造函数。这也没有意义,因为每次构造新实例时都会一遍又一遍地调用代码,而 const 应该只设置一次。
如果 PHP 提供某种静态构造函数让您为未初始化的常量设置一次值,或者在定义常量时允许更多类型的表达式,那就太好了。但这些目前还不是 PHP 的特性。 2015 年提出了一个 RFC 建议添加静态类构造函数,但在我撰写此答案时,它仍处于草稿状态,自 2017 年以来未修改。
我认为目前最好的选择是在这种情况下不使用常量,而是使用返回所需值的静态方法。这很简单,它只使用 PHP 语言的特性(不需要任何特殊的扩展),这些静态方法可以以标准的方式调用,你不需要破解自动加载过程来调用某种设置静态变量的初始化函数。如果要返回对象实例,该方法可能需要依赖私有静态变量,以确保每次都返回相同的实例。您需要将此方法的实现编写为常量,就像它总是返回相同的东西一样,但是利用能够做您不能用常量做的事情的优势,例如返回对象实例或依赖于复杂的表达式或函数调用。这是一个例子:
final class User
{
/** @var DefinitelyPositiveInt|null */ private static $usernameMaxLength;
public static function getUsernameMaxLengthConst(): DefinitelyPositiveInt
{
if ($usernameMaxLength === null) {
$usernameMaxLength = new DefinitelyPositiveInt(40);
}
return $usernameMaxLength;
}
}
$usernameInput.maxLength = User::getUsernameMaxLengthConst();
这仍然不是一个完美的解决方案,因为它依赖于程序员在需要时以类似常量的方式编写这些(总是返回相同的值)。另外,我不喜欢在方法名称中记录它是 const 事实的最佳位置,从而使其调用时间更长。我也不喜欢你现在必须将它作为一种方法来调用,而不是仅仅访问一个属性,这在语法上会更好。
这个例子本质上是一个单例的实现,但有时单例的目的是成为一个常量而不仅仅是一个单例。我的意思是,您可能希望实例始终存在,并且它可能是不可变类型(所有属性都不是公共的或可变的,只有返回新对象/值的方法)。
【讨论】:
很抱歉打扰您,但在普通 PHP 中是不可能的。 我不太确定框架或扩展,但我确信在原生 PHP 中是不可能的。 我建议您改用变量。
【讨论】:
你仍然不能,但也许其中一些(越来越奇怪的)想法(只是想法,而不是真正的解决方案)对你有用:
(1) 您可以使用私有属性,以及public getter 方法。属性不能在类外修改,比如常量,可惜是作为方法访问,而不是作为常量访问,所以语法不一样。
class aClass{
private $const;
function __construct($const){
$this->const=$const;
}
function const(){
return $this->const;
}
}
$var1=new aClass(1);
echo $var1->const(); //Prints 1
(2) 如果你真的希望这个值作为常量从外部访问,你可以在构造函数中使用define ()。不幸的是,它与类或对象名称无关(就像您使用 const 时所做的那样,例如使用 myClass::myConst)。此外,它仅在您创建该类的单个实例时才有效。您创建的第二个对象将在重新定义常量时引发错误,因为它是未绑定的。
class otherClass{
function __construct($const){
define('_CONST',$const);
}
function const(){
return _CONST;
}
}
$var2=new otherClass('2');
echo $var2->const(); //Prints 2
echo _CONST; //Prints 2
@$var3=new aClass('3'); //Notice: Constant _CONST already defined
echo _CONST; //Still prints 2!
(3) 也许最后一个问题可以通过为常量赋予变量名来解决,这与它们所属的对象相关。这可能有点奇怪......但也许它适用于某人。
class onemoreClass{
private $name;
function __construct($const,$name){
$this->name=$name;
$constname=$this->name."_CONST";
define($constname,$const);
}
function const(){
return constant($this->name.'_CONST');
}
}
$name='var4';
$$name=new onemoreClass(4,$name);
echo $var4->const(); //Prints 4
echo var4_CONST; //Prints 4
$name='var5';
$$name=new onemoreClass(5,$name);
echo $var5->const(); //Prints 5
echo var5_CONST; //Prints 5
【讨论】: