如何实例化抽象 class 的 child 单例?
How to instantiate a child singleton of an abstract class?
我有一个摘要 class 和一个扩展摘要 class 的 child。 child 应该是单例。这是摘要 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;
}
}
这里是简化的child class:
class ChildClass_A extends AbstractClass{
protected function meInit(){
'some code;
}
}
当我尝试获取 child $child = ChildClass_A::getInstance();
的实例时,出现此错误:
Fatal error: Cannot instantiate abstract class AbstractClass in
C:\wamp\www\Classes\AbstractClass.php on line 7
我怀疑罪魁祸首在 self::$instance=new self;
。我应该如何重做才能达到我需要的效果?
你快到了;你不能像这样使用 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?
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
实例!这是因为抽象 class A 只保存了一个实例。我们必须让它支持每个 subclass.
之一
嗯,这很简单!
// 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
和 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) {}
哦,太好了!正是我们一直想要的!
我有一个摘要 class 和一个扩展摘要 class 的 child。 child 应该是单例。这是摘要 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;
}
}
这里是简化的child class:
class ChildClass_A extends AbstractClass{
protected function meInit(){
'some code;
}
}
当我尝试获取 child $child = ChildClass_A::getInstance();
的实例时,出现此错误:
Fatal error: Cannot instantiate abstract class AbstractClass in C:\wamp\www\Classes\AbstractClass.php on line 7
我怀疑罪魁祸首在 self::$instance=new self;
。我应该如何重做才能达到我需要的效果?
你快到了;你不能像这样使用 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?
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
实例!这是因为抽象 class A 只保存了一个实例。我们必须让它支持每个 subclass.
嗯,这很简单!
// 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
和 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) {}
哦,太好了!正是我们一直想要的!