我想使用私有构造函数实现以下内容。
问题是get_class()
返回ParentBase
;即使; get_called_class()
会返回ChildClass
。
如何从调用类上下文而不是基类上下文中调用__construct()?
会有很多子类,所以我只想要一个共享工厂方法,并且我还想确保无法扩展子项(因此无法使用new关键字创建)。
似乎应该有一种方法可以使ChildClass::createObject()
使用私有ChildClass
构造函数和公共ParentBase
工厂方法。
<?php
class ParentBase
{
public static function createObject()
{
echo get_class() . "<br/>"; // prints ParentBase
echo get_called_class() . "<br/>"; // prints ChildClass
return new static();
}
}
class ChildClass extends ParentBase
{
private $greeting = "bye";
private function __construct()
{
$this->greeting = "hi";
}
public function greet()
{
echo $this->greeting;
}
}
$child = ChildClass::createObject();
$child->greet();
以上的输出是:
ParentBase
ChildClass
Fatal error: Call to private ChildClass::__construct() from context 'ParentBase'
受保护的contstructor工作原理: http://codepad.viper-7.com/sCgJwA
私有构造函数不: http://codepad.viper-7.com/YBs7Iz
答案 0 :(得分:1)
这是预期的行为createObject();
是ParentBase
的函数,因此它将从ParentBase
返回get_class()
但是,它是从ChildClass
调用的,它将从ChildClass
返回get_called_class()
。
关于构造函数,由于构造函数被指定为private,因此只能在类中限制对象创建。通过使其受到保护,现在Parent Class可以创建ChildClass
可能的解决方案是覆盖createObject()
本身的ChildClass
类。
class ChildClass extends ParentBase
{
public static function createObject()
{
echo get_class() . "<br/>";
echo get_called_class() . "<br/>";
return new static();
}
}
或者,您可以使构造函数受到保护,然后您将使构造函数可以访问父类并限制子类的任何子类使其成为最终类,从而使其只能从父类访问。
答案 1 :(得分:0)
根据我的知识,子构造函数必须受到保护或公开。我针对另一个问题遇到了类似的问题,我试图访问私有财产。
但出于某种原因你的问题&#34;我可以从基础工厂方法调用私有子构造函数吗?&#34;并不反映你的代码所以我建议你编辑,因为我在如何回答这个问题时遇到了麻烦。
答案 2 :(得分:0)
如果这是PHP 5.4 ......
在玩了一些其他的事情并阅读PHP OOP之后。看起来Traits可以做到这一点。
我喜欢use Trait
notataion,在这种情况下很明显你应该使用Factory来实例化类。
使用Trait是有利的,因为Factory Trait可以在没有共同谱系的多个Class层次结构中共享:
<?php
// NOTE: traits are only avaialable in ** PHP 5.4 **
trait Factory
{
public static function createObject()
{
echo get_class() . "<br/>"; // prints ChildClass
echo get_called_class() . "<br/>"; // prints ChildClass
return new static();
}
}
class ChildClass
{
use Factory;
private $greeting = "bye";
private function __construct()
{
$this->greeting = "hi";
}
public function greet()
{
echo $this->greeting;
}
}
$child = ChildClass::createObject();
$child->greet();
<强> Working Code Example 强>