I have an abstract class and a child that extends the abstract class. The child is supposed to be a sigleton. Here is simplified example of the abstract class:
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;
}
}
Here is simplified child class:
class ChildClass_A extends AbstractClass{
protected function meInit(){
'some code;
}
}
When I try to get an instance of the child $child = ChildClass_A::getInstance();
I get this error:
Fatal error: Cannot instantiate abstract class AbstractClass in C:\wamp\www\Classes\AbstractClass.php on line 7
I suspect the culprit is in self::$instance=new self;
. How should I redo it to achieve what I need?
You're almost there; you just can't use new self()
like this because it's trying to do a new A()
. Instead, use get_called_class()
so that a new B
is created instead.
// 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) {}
OK, but what happens now when we try to make another subclass?
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) {}
Well that sucks! I wanted a C
instance, not the B
one! This is because the abstract class A is only saving one instance. We have to make it support one of each subclass.
Well that's easy!
// 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];
}
}
Class B
and C
can stay the same ...
class B extends A {
protected function __construct() {
echo "constructing B\n";
}
}
class C extends A {
protected function __construct() {
echo "constructing C\n";
}
}
Now let's check out how they behave
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) {}
Oh good! Just what we always wanted!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With