简体   繁体   English

如何在类构造函数中定义常量?

[英]How to define constant in class constructor?

Can I define a class constant inside the class constructor function ?我可以在类构造函数中定义一个类常量吗?

(based on certain conditions) (基于特定条件)

That goes against the idea of class constants - they should not be dependent on a specific instance.这与类常量的想法背道而驰——它们不应该依赖于特定的实例。 You should use a variable instead.您应该改用变量。

However, if you insist on doing this, are very adventurous and can install PHP extensions, you can have a look at the runkit extension that allows to modify classes and their constants at runtime.但是,如果您坚持这样做,非常喜欢冒险并且可以安装 PHP 扩展,则可以查看允许在运行时修改类及其常量的 runkit 扩展。 See this doc: http://www.php.net/manual/en/function.runkit-constant-add.php请参阅此文档: http : //www.php.net/manual/en/function.runkit-constant-add.php

I don't think you can.我不认为你可以。

It wouldn't make sense, either - a class constant can be used in a static context, where there is no constructor in the first place.这也没有意义 - 类常量可以在静态上下文中使用,其中首先没有构造函数。

You'll have to use a variable instead - that's what they're there for.您将不得不改用变量 - 这就是它们的用途。

As far as standard instance constructors go, there is no way to do this, and as others have pointed out, it wouldn't make sense.就标准实例构造函数而言,没有办法做到这一点,正如其他人指出的那样,这是没有意义的。 These constructors are called per created object instance, at the point they are created.这些构造函数在每个创建的对象实例被创建时被调用。 There is no guarantee this constructor would get called before some code tried to access the constant.无法保证在某些代码尝试访问常量之前会调用此构造函数。 It also doesn't make sense in that the code would get called over and over again each time a new instance was constructed, whereas a const should only get set once.这也没有意义,因为每次构造一个新实例时,代码都会被一遍又一遍地调用,而 const 应该只设置一次。

It would be nice if PHP either offered some kind of static constructor that let you set the value one time for uninitialized constants, or allowed more types of expressions when defining constants.如果 PHP 提供某种静态构造函数让您为未初始化的常量设置一次值,或者在定义常量时允许更多类型的表达式,那就太好了。 But these are not currently features of PHP.但这些目前都不是 PHP 的特性。 In 2015 an RFC was made that proposed adding static class constructors, but it is, at the time of me writing this answer, still in the draft status, and has not been modified since 2017. 2015 年提出了一个RFC ,建议添加静态类构造函数,但在我写这个答案时,它仍处于草案状态,并且自 2017 年以来没有修改。

I think the best alternative for now is to not use constants in this kind of scenario, and instead use static methods that return the value you want.我认为目前最好的选择是在这种情况下不使用常量,而是使用返回所需值的静态方法。 This is very simple in that it only uses the PHP language features as is (not requiring any special extensions), these static methods can be called in the standard way, and you don't need to hack the autoloading process to call some kind of initializer function that sets static variables.这很简单,因为它只按原样使用 PHP 语言功能(不需要任何特殊扩展),这些静态方法可以以标准方式调用,并且您不需要破解自动加载过程来调用某种设置静态变量的初始化函数。 The method might need to rely on private static variables in order to make sure the same instance is returned every time, if an object instance is being returned.如果正在返回对象实例,该方法可能需要依赖私有静态变量以确保每次都返回相同的实例。 You would need to write the implementation of this method to be constant like in the sense that it will always return the same thing, but takes advantage of being able to do things you can't do with a constant, like return on object instance or rely on complex expressions or function calls.您需要将此方法的实现编写为常量,就像它总是返回相同的东西一样,但利用能够执行常量无法执行的操作,例如返回对象实例或依赖复杂的表达式或函数调用。 Here is an example:下面是一个例子:

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();

This is still not a perfect solution because it relies on the programmer to write these in a constant like way when that is desired (always returning the same value).这仍然不是一个完美的解决方案,因为它依赖于程序员在需要时以类似常量的方式编写这些(始终返回相同的值)。 Also, I don't like that the best place to document the fact that it is a const is in the method name, thus making it even longer to call.另外,我不喜欢在方法名称中记录它是 const 的事实的最佳位置,从而使其调用时间更长。 I also don't like that you now have to call it as a method instead of just accessing a property, which would be syntactically nicer.我也不喜欢您现在必须将其作为方法调用,而不仅仅是访问属性,这在语法上会更好。

This example is essentially an implementation of a singleton, but sometimes the purpose of a singleton is to be a constant rather than just a singleton.这个例子本质上是一个单例的实现,但有时单例的目的是成为一个常量而不仅仅是一个单例。 What I mean is, you might want the instance to always exist, and it might be an immutable type (none of the properties are public or mutable, only having methods that return new objects/values).我的意思是,您可能希望实例始终存在,并且它可能是不可变类型(没有一个属性是公共的或可变的,只有返回新对象/值的方法)。

I am sorry to break it to you but it is not possible in vanilla PHP.很抱歉打扰您,但在普通 PHP 中这是不可能的。 I am not very sure about frameworks or extensions but I am sure that it is not possible in vanilla PHP.我对框架或扩展不是很确定,但我确信在普通 PHP 中这是不可能的。 I recommend you to use variables instead.我建议您改用变量。

You still can't , but maybe some of these (progressively weirder) ideas (just ideas, not true solutions) will work for you:你仍然不能,但也许其中一些(逐渐变得奇怪的)想法(只是想法,而不是真正的解决方案)对你有用:

(1) You could use a private property , with a public getter method . (1) 您可以使用私有属性公共 getter方法 The property cannot be modified outside the class, such as constants, but unfortunately it is accessed as a method, not as a constant, so the syntax is not the same.不能在类外修改属性,比如常量,但遗憾的是它是作为方法访问的,而不是作为常量访问,所以语法不一样。

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) If you really want this value to be accessed as constant from outside, you can use define () inside the constructor . (2) 如果你真的希望这个值作为常量从外部访问,你可以在构造函数内部使用define () Unfortunately it doesn't get tied to the class or object name (as it do when you use const , using for example myClass::myConst ).不幸的是,它没有绑定到类或对象名称(就像使用const 时一样,例如使用myClass::myConst )。 Furthermore, it only works if you create a single instance of the class.此外,它仅在您创建类的单个实例时才有效。 The second object you create is going to throw an error for redefining the constant, because is untied.您创建的第二个对象将因重新定义常量而引发错误,因为未绑定。

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) Perhaps that last problem can be solved by giving variable names to the constants , related to the object to which they belong. (3) 也许最后一个问题可以通过给与它们所属的对象相关的常量命名变量来解决。 This may be a bit weird... but maybe it works for someone.这可能有点奇怪……但也许它对某人有用。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM