我可以从基础工厂方法调用私有子构造函数吗?

时间:2012-08-21 02:28:02

标签: php factory

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

问题是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

3 个答案:

答案 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