PHP Расширение класса заставляет детей наследовать одно и то же статическое свойство

Я хотел бы начать с показа теста:

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! 

Заметки

  • Я использую шаблон фабрики + singleton выше. Ну, немного.
  • Мне не нужны какие-либо спецификации «правильной реализации шаблонов». Мне нужно решение проблем, а не нарушения KISS;).
  • Критики могут сказать, что A должен быть интерфейсом. В идеале, это то, что должно было быть, но это просто класс, извините.

Проблемы заключаются в том, что self::$instance одинаково для всех экземпляров. Как отделить self::$instance для каждого класса?

Edit: У меня была эта идея:

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

Related of "PHP Расширение класса заставляет детей наследовать одно и то же статическое свойство"

Вы можете сохранить экземпляр для каждого имени класса:

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

Вы не можете сделать это чистым способом. Это один из недостатков мэра по свойствам stati: вы не можете их переопределить.

Но вы хотите, чтобы решение было таким … вот что беспокоит: используйте __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»;

Вы можете добавить public static $instance=null; декларация в классе 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.