【问题标题】:How to define constant in class constructor?如何在类构造函数中定义常量?
【发布时间】:2011-10-31 23:48:38
【问题描述】:

我可以在类构造函数中定义一个类常量吗?

(基于某些条件)

【问题讨论】:

    标签: php class constants


    【解决方案1】:

    这与类常量的想法背道而驰——它们不应该依赖于特定的实例。您应该改用变量。

    但是,如果您坚持这样做,并且非常冒险并且可以安装 PHP 扩展,您可以查看允许在运行时修改类及其常量的 runkit 扩展。请参阅此文档:http://www.php.net/manual/en/function.runkit-constant-add.php

    【讨论】:

    • 我正在寻找可以在构造函数中设置的 java 的 static final 的 php 等效项,但不幸的是 php 中的常量有点不同。
    • 这也违背了一般常量的想法,但是在 PHP 中你可以动态地定义()一个常量。
    • 当您想要定义其值由其他常量的值组成的字符串常量时(为了干燥公共部分),这可能很有用。由于 PHP 不允许常量值中的表达式(例如连接两个字符串),因此在构造函数中执行此操作会很有用。
    • 我不认为“类常量”意味着静态。拥有非静态类常量是一个有效的概念。不幸的是,PHP 在这方面似乎受到限制,并且没有针对它的语法/行为。在像 C++ 这样的语言中,具有实例级常量是很常见的。它们必须通过初始化列表设置,但您可以使用其他变量、构造函数参数甚至函数来设置初始值。这非常有用,希望 PHP 有朝一日能解决它。
    • @Daniel 听起来更像是一个只读属性,或者一个在最初设置后不可变的属性,而不是一个常量。常量确实意味着静态,因为它在不同的情况下不应该不同。但我同意能够从某种构造函数(可能是静态构造函数)设置值会很好,这样它就可以设置为 php 不允许你做的事情,比如将它设置为一个对象实例。
    【解决方案2】:

    我不认为你可以。

    这也没有意义 - 类常量可以在静态上下文中使用,其中首先没有构造函数。

    您必须改用变量 - 这就是它们的用途。

    【讨论】:

    • 如果您能够从某种不同于实例构造函数的静态构造函数中做到这一点,我会说得通。它需要保证在使用常量之前运行。这似乎相似:wiki.php.net/rfc/static_class_constructor
    【解决方案3】:

    【讨论】:

    • 公共静态$变量
    【解决方案4】:

    就标准实例构造函数而言,没有办法做到这一点,正如其他人指出的那样,这没有意义。这些构造函数在它们被创建时被每个创建的对象实例调用。无法保证在某些代码尝试访问该常量之前会调用此构造函数。这也没有意义,因为每次构造新实例时都会一遍又一遍地调用代码,而 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 事实的最佳位置,从而使其调用时间更长。我也不喜欢你现在必须将它作为一种方法来调用,而不是仅仅访问一个属性,这在语法上会更好。

    这个例子本质上是一个单例的实现,但有时单例的目的是成为一个常量而不仅仅是一个单例。我的意思是,您可能希望实例始终存在,并且它可能是不可变类型(所有属性都不是公共的或可变的,只有返回新对象/值的方法)。

    【讨论】:

      【解决方案5】:

      很抱歉打扰您,但在普通 PHP 中是不可能的。 我不太确定框架或扩展,但我确信在原生 PHP 中是不可能的。 我建议您改用变量。

      【讨论】:

        【解决方案6】:

        你仍然不能,但也许其中一些(越来越奇怪的)想法(只是想法,而不是真正的解决方案)对你有用:

        (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
        

        【讨论】:

          猜你喜欢
          • 2011-12-27
          • 2016-05-16
          • 2023-03-03
          • 2020-10-18
          • 2018-05-25
          • 2021-04-28
          • 2015-07-24
          • 2019-08-26
          • 1970-01-01
          相关资源
          最近更新 更多