Как создать экземпляр дочернего синглтона абстрактного класса?

У меня есть абстрактный класс и ребенок, который расширяет абстрактный класс. Ребенок должен быть сиглетом. Вот упрощенный пример абстрактного класса:

abstract class AbstractClass{
protected static $instance = NULL;
abstract protected function meInit();

private function __construct(){
$this->meInit();
$this->init();
}

private function __clone(){}

static function getInstance(){
if (is_null(self::$instance)){
self::$instance=new self;
}
return self::$instance;
}

function init(){
'code here;

}
}

Вот упрощенный дочерний класс:

class ChildClass_A extends AbstractClass{

protected function meInit(){
'some code;
}
}

Когда я пытаюсь получить экземпляр ребенка $child = ChildClass_A::getInstance(); Я получаю эту ошибку:

Неустранимая ошибка: невозможно создать экземпляр абстрактного класса AbstractClass в
C: \ wamp \ www \ Classes \ AbstractClass.php в строке 7

Я подозреваю, что виновник в self::$instance=new self;, Как мне переделать это, чтобы добиться того, что мне нужно?

4

Решение

Ты почти там; ты просто не можешь использовать new self() как это, потому что он пытается сделать new A(), Вместо этого используйте get_called_class() так что новый B создается вместо.

// ONLY SUPPORTS ONE SUBCLASS
// KEEP READING BELOW FOR COMPLETE SOLUTION
abstract class A {

static protected $instance = null;

abstract protected function __construct();

static public function getInstance() {
if (is_null(self::$instance)) {
$class = get_called_class();
self::$instance = new $class();
}
return self::$instance;
}

}

class B extends A {
protected function __construct() {
echo "constructing B\n";
}
}

var_dump(B::getInstance()); // constructing B, object(B)#1 (0) {}
var_dump(B::getInstance()); // object(B)#1 (0) {}

Хорошо, но что происходит сейчас, когда мы пытаемся создать другой подкласс?

class C extends A {
protected function __construct() {
echo "constructing C\n";
}
}

var_dump(C::getInstance()); // object(B)#1 (0) {}
var_dump(C::getInstance()); // object(B)#1 (0) {}

Ну, это отстой! Я хотел C экземпляр, а не B один! Это потому, что абстрактный класс сохраняет только один экземпляр. Мы должны сделать так, чтобы он поддерживал один из каждого подкласса.

Ну, это легко!

// SOLUTION:
// WORKS FOR MULTIPLE SUBCLASSES
abstract class A {

static protected $instances = array();

abstract protected function __construct();

static public function getInstance() {
$class = get_called_class();
if (! array_key_exists($class, self::$instances)) {
self::$instances[$class] = new $class();
}
return self::$instances[$class];
}

}

Учебный класс B а также C может остаться прежним …

class B extends A {
protected function __construct() {
echo "constructing B\n";
}
}

class C extends A {
protected function __construct() {
echo "constructing C\n";
}
}

Теперь давайте посмотрим, как они себя ведут

var_dump(B::getInstance()); // constructing B, object(B)#1 (0) {}
var_dump(B::getInstance()); // object(B)#1 (0) {}

var_dump(C::getInstance()); // constructing C, object(C)#2 (0) {}
var_dump(C::getInstance()); // object(C)#2 (0) {}

О, хорошо! Как раз то, что мы всегда хотели!

8

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector