当前位置:  开发笔记 > 编程语言 > 正文

如何初始化静态变量

如何解决《如何初始化静态变量》经验,为你挑选了5个好方法。

我有这个代码:

private static $dates = array(
  'start' => mktime( 0,  0,  0,  7, 30, 2009),  // Start date
  'end'   => mktime( 0,  0,  0,  8,  2, 2009),  // End date
  'close' => mktime(23, 59, 59,  7, 20, 2009),  // Date when registration closes
  'early' => mktime( 0,  0,  0,  3, 19, 2009),  // Date when early bird discount ends
);

这给了我以下错误:

解析错误:第19行/home/user/Sites/site/registration/inc/registration.class.inc中的语法错误,意外'(',期待')'

所以,我想我做错了什么......但是如果不是那样的话怎么办呢?如果我用常规字符串更改mktime内容,它就可以工作.所以,我知道我能做到这一点的那种像..

有人有指点吗?



1> Kornel..:

PHP无法解析初始值设定项中的非平凡表达式.

我更喜欢通过在定义类之后添加代码来解决这个问题:

class Foo {
  static $bar;
}
Foo::$bar = array(…);

要么

class Foo {
  private static $bar;
  static function init()
  {
    self::$bar = array(…);
  }
}
Foo::init();

PHP 5.6现在可以处理一些表达式.

/* For Abstract classes */
abstract class Foo{
    private static function bar(){
        static $bar = null;
        if ($bar == null)
            bar = array(...);
        return $bar;
    }
    /* use where necessary */
    self::bar();
}


我喜欢PHP,但有时候真的很奇怪.
我知道这是旧的,但我也使用这种方法.但是,我发现有时候不会调用Foo :: init().我从来没有能够找到原因,但只是想让所有人意识到.
@Pacerier第一种方法使用公共财产是有原因的。AFAIK目前在PHP中没有更好的解决方案(尽管Tjeerd Visser的回答还不错)。隐藏在类加载器中的hack不会使其消失,会导致错误的继承,并且它的一些聪明之处可能会使其意外中断(例如,当文件需要require()d时)。

2> Emanuel Land..:

如果您可以控制类加载,则可以从那里进行静态初始化.

例:

class MyClass { public static function static_init() { } }

在类加载器中,执行以下操作:

include($path . $klass . PHP_EXT);
if(method_exists($klass, 'static_init')) { $klass::staticInit() }

更重的解决方案是使用ReflectionClass的接口:

interface StaticInit { public static function staticInit() { } }
class MyClass implements StaticInit { public static function staticInit() { } }

在类加载器中,执行以下操作:

$rc = new ReflectionClass($klass);
if(in_array('StaticInit', $rc->getInterfaceNames())) { $klass::staticInit() }



3> 小智..:

我没有找到让静态变量工作的方法,而是简单地创建一个getter函数.如果您需要属于特定类的数组,并且实现起来要简单得多,也会很有帮助.

class MyClass
{
   public static function getTypeList()
   {
       return array(
           "type_a"=>"Type A",
           "type_b"=>"Type B",
           //... etc.
       );
   }
}

无论您需要列表,只需调用getter方法即可.例如:

if (array_key_exists($type, MyClass::getTypeList()) {
     // do something important...
}


"在没有必要时最好避免使用它们" - 不是真的.如果他们(可能)成为瓶颈,请避免使用它们.否则就是过早优化.
虽然这是一个优雅的解决方案,但我不认为它是出于性能原因的理想选择,主要是因为数组可能被初始化的次数 - 即大量的堆分配.由于php是用C语言编写的,我想这个翻译会解析为每个调用返回一个指向数组的指针的函数......只需要我的两分钱.
我真的不想试图避免函数调用.函数是结构化编程的基础.
@blissfreak-如果我们在类中创建一个静态属性,并检查getTypeList()是否已经初始化并返回它,则可以避免实现。如果尚未初始化,则将其初始化并返回该值。

4> 小智..:

我使用了Tjeerd Visser和porneL的答案.

class Something
{
    private static $foo;

    private static getFoo()
    {
        if ($foo === null)
            $foo = [[ complicated initializer ]]
        return $foo;
    }

    public static bar()
    {
        [[ do something with self::getFoo() ]]
    }
}

但更好的解决方案是取消静态方法并使用Singleton模式.然后你只需要在构造函数中进行复杂的初始化.或者将其作为"服务"并使用DI将其注入任何需要它的类中.



5> Alister Bulm..:

这太复杂了,无法在定义中设置.您可以将定义设置为null,然后在构造函数中检查它,如果它还没有更改 - 设置它:

private static $dates = null;
public function __construct()
{
    if (is_null(self::$dates)) {  // OR if (!is_array(self::$date))
         self::$dates = array( /* .... */);
    }
}


但构造函数是否会在一个从未实例化的抽象类中提供任何帮助?
@AlisterBulman,他的意思是静态类的静态方法
推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有