1

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

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

4

3 回答 3

1

那是一个预期的行为createObject();是一个函数ParentBase,所以它会从返回ParentBaseget_class()但是,它是从调用的,所以它会从ChildClass返回。ChildClassget_called_class()

关于构造函数,由于构造函数被指定为私有的,因此您只能在类中限制对象的创建。通过使其受到保护,现在父类可以创建对象ChildClass

可能的解决方案是覆盖本身的createObject()类。ChildClass

class ChildClass extends ParentBase
{
    public static function createObject() 
    {
        echo get_class() . "<br/>";
        echo get_called_class() . "<br/>";
        return new static();
    }
}

或者,您可以使构造函数受保护,然后您将使构造函数可被父类访问,并限制子类的任何子类使其成为最终的,从而使其只能从父类访问。

于 2012-08-21T02:40:28.993 回答
0

如果这是 PHP 5.4……

在玩了一些其他的东西并阅读了 PHP OOP 之后。看起来 Traits 可以做到这一点。

我喜欢这种use Trait表示法,在这种情况下,很明显你应该使用工厂来实例化类。

使用 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();

工作代码示例

于 2012-08-21T06:18:28.280 回答
0

据我所知,子构造函数必须受到保护或公开。我遇到了一个不同的问题,我试图访问一个私有财产。

但是由于某种原因,您的问题“我可以从基本工厂方法调用私有子构造函数吗?” 不反映您的代码,因此我建议您对其进行编辑,因为我正在为如何回答这个问题而烦恼。

于 2012-08-21T02:30:28.837 回答