PHP扩展类使子级继承相同的静态属性

时间:2010-12-17 15:50:44

标签: php static singleton properties factory

我想首先展示一个测试用例:

class A {
    public static $instance=null;
    public function __construct(){
        self::$instance=$this;
    }
    public function className(){
        return get_class(self::$instance);
    }
}

class B extends A {
    public function className(){
        return get_class(self::$instance);
    }
}

// test code
$b=new B();
echo $b->className; // B
$a=new A();
echo $a->className; // A
echo $b->className; // A <- error: not B any more!

备注

  • 我正在使用上面的工厂+单身模式。好吧,有点。
  • 我不需要任何关于“正确实现模式”的规范。我需要解决问题,而不是KISS违规;)。
  • 批评者可能会说A应该是一个界面。理想情况下,这应该是应该的,但它只是一个简单的课程,对不起。

问题在于self::$instance对于所有实例都是相同的。如何为每个班级分隔self::$instance

编辑:我有这个想法:

$GLOBALS['store']=array();
class A {
    public static $instance=null;
    public function __construct(){
        $GLOBALS['store'][__CLASS__]=$this;
    }
}

3 个答案:

答案 0 :(得分:3)

您可以按类名存储实例:

class A { 
    public static function getInstance(){
        // Maybe use this function to implement the singleton pattern ...
        return self::$instance[get_called_class()];
    }

    public function className(){
        return get_class(self::getInstance());
    }   
}

答案 1 :(得分:1)

你无法以干净的方式做到这一点。  这是stati propertys的市长缺点之一:你无法覆盖它们。

但是你想要一个解决方案,所以.....这里是worarround: 使用__calllStatic

  <?php 
 class A {
    public static function __callstatic($name,$args)
    {
        if($name="getClass"){
                return 'A';
        }
    }
 }

 class  B extends  A{
 public static function __callstatic($name,$args)
    {
        if($name="getClass"){
                return 'B';
        }
    }
 }


echo  A::getClass();
echo  B::getClass();
?>

这个输出是“AB”;

答案 2 :(得分:1)

您可以在B类中添加public static $instance=null;声明。

class A {
    public static $instance=null;
    public function __construct(){
        self::$instance=$this;
    }
    public function className(){
        return get_class(self::$instance);
    }
}

class B extends A {
    public static $instance=null;
    public function className(){
        return get_class(self::$instance);
    }
}

// test code
$b=new B();
echo $b->className(); // B
$a=new A();
echo $a->className(); // A
echo $b->className(); // Now returns B, as desired.