我想使用私有构造函数实现以下内容。
问题是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'
受保护的施工人员作品:http://codepad.viper-7.com/sCgJwA
私有构造函数不会:http://codepad.viper-7.com/YBs7Iz
预期的行为createObject();
是ParentBase
的函数,所以它会从get_class()
返回ParentBase
但是,它是从ChildClass
调用的,所以它会从get_called_class()
返回ChildClass
。
关于构造函数,由于构造函数被分配为私有的,因此您只能从类中限制对象的创建。通过使其受到保护,现在父类可以创建ChildClass
的对象
可能的解决方案是覆盖ChildClass
本身中的createObject()
类。
class ChildClass extends ParentBase
{
public static function createObject()
{
echo get_class() . "<br/>";
echo get_called_class() . "<br/>";
return new static();
}
}
或者,您可以使构造函数受到保护,然后您将使构造函数可供父类访问,并限制子类的任何子类使其成为最终类,从而使它只能从父类访问。
子构造函数必须受到保护或公开。我遇到了一个类似的问题,我试图访问一个私有财产。
但是出于某种原因,您的问题"我可以从基本工厂方法调用私有子构造函数吗?"并不反映您的代码,所以我建议您对其进行编辑,因为我正在为如何回答这个问题而烦恼。
如果这是 PHP 5.4......
在玩了一些其他东西并阅读了 PHP OOP 之后。看起来特质可以做到这一点。
我喜欢 use Trait
notataion,在这种情况下,很明显你应该使用工厂来实例化类。
使用特征是有利的,因为它可以在没有共同谱系的多个类层次结构之间共享工厂特征:
<?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();
工作代码示例