是否可以从基工厂方法调用私有子构造函数


Can I call a private child constructor from a base factory method?

我想使用私有构造函数实现以下内容。

问题是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();

工作代码示例