PHP Extending class makes children inherit same st

2019-05-22 16:38发布

问题:

I'd like to start by showing a test case:

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!

Notes

  • I'm using a factory+singleton patterns above. Well, somewhat.
  • I don't need any specs on "implementing patterns correctly". I need problem solving, not KISS violations ;).
  • Critics might say A should be an interface. Ideally, that's what it should have been, but it's just a simple class, sorry.

The issues lies in the fact that self::$instance is the same for all instances. How do I separate self::$instance for each class?

Edit: I've had this idea:

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

回答1:

You could store an instance per class name:

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


回答2:

You can not do this the clean way. That is one of the mayor drawbacks on stati propertys: you cannot overrride them.

But you wantet an sollution so.....here is the worarround: use __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();
?>

the output of this is "AB";



回答3:

You can add a public static $instance=null; declaration in class B.

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.