打破构造函数

时间:2011-01-26 11:09:54

标签: php oop

有没有办法阻止在其构造函数中创建对象,以便:

$object = new Foo();
echo $object; // outputs: NULL

5 个答案:

答案 0 :(得分:14)

不,不可能;无论您尝试从构造函数返回什么,new关键字始终都会返回指定类的实例。这是因为在调用构造函数时,PHP已经为新对象分配了内存。换句话说,对象在那时已经存在(否则,根本就没有对象可以调用构造函数)。

您可能会引发错误或从构造函数中抛出异常,并相应地处理它们。

class Foo {
    public function __construct() {
        throw new Exception('Could not finish constructing');
    }
}

try {
    $object = new Foo();
} catch (Exception $e) {
    echo $e->getMessage();
}

答案 1 :(得分:3)

不可能,但你可以proxify the creation

<?php

class Foo {
    private function __construct() {}

    static function factory($create=False) {
        if ($create) {
            return new Foo;
        }
    }
}

答案 2 :(得分:2)

简单地抛出异常:

throw new Exception('thou shalt not be born!');

答案 3 :(得分:1)

您可以实现工厂为您创建对象。如果您使用的是PHP 5.3.0+,则可以访问名为Late Static Binding的功能,这样可以轻松实现。

<?php
class MyObject
{
    protected $loadSuccess = false;

    protected function __construct ($foo, $bar, $baz)
    {
        // Just a random 50/50 success probability.  Put real logic for testing success here
        $this -> loadSuccess    = (mt_rand (0, 99) > 49);
    }

    static public function factory ($foo, $bar, $baz)
    {
        $objClass   = get_called_class ();
        $obj = new $objClass ($foo, $bar, $baz);
        if ($obj -> loadSuccess)
        {
            return ($obj);
        }
    }
}

class MySubClass extends MyObject
{
    protected function __construct ($foo, $bar, $baz)
    {
        parent::__construct ($foo, $bar, $baz);
        if ($this -> loadSuccess)
        {
            echo ('Hello, I\'m a ' . get_called_class () . '<br>');
        }
    }
}

class MySubSubClass extends MySubClass
{
    protected function __construct ($foo, $bar, $baz)
    {
        parent::__construct ($foo, $bar, $baz);
        if ($this -> loadSuccess)
        {
            echo ($foo * $bar * $baz . '<br>');
        }
    }
}

$o1 = MyObject::factory (1, 2, 3); // Base class
$o2 = MySubClass::factory (4, 5, 6); // Child class
$o3 = MySubSubClass::factory(7, 8, 9); // Descendent class

var_dump ($o1);
var_dump ($o2);
var_dump ($o3);
?>

如果您使用的是5.3.0之前的PHP版本,那么由于后期静态绑定和get_called_class()不可用,事情会变得复杂一些。但是,PHP 5确实支持反射,您可以使用它来模拟后期静态绑定。或者,您可以实现一个单独的工厂类并向其传递一个参数,告诉它要初始化的对象类型。

另一种方法是让构造函数在失败时抛出异常并使用catch块处理它。但是,如果你正在做很多事情,这种方法可能会变得多毛,而且它应该只在你通常期望对象创建成功时使用(换句话说,如果创建失败是一种特殊情况)。

工厂方法还有其他优点,例如它可以保存已经创建的对象的缓存,如果您尝试创建两次相同的对象,它只会传递一个已经初始化的对象的引用,而不是创建一个新的。这消除了对象创建中固有的内存和处理开销,尤其是在创建涉及时间密集型任务(如复杂的SQL查询)的情况下

答案 4 :(得分:0)

如果您尝试根据一些条件阻止对象实例化,那么为什么不在创建PHP new之前创建一个条件并实例化该类?

我的意思是,在你的例子中说:

$object = new Foo();
echo $object; // outputs: NULL

你可以将它包装在一个为你进行验证工作的函数中,或者只是一个if语句,如果你只是要实例化一次类。

像这样:

if(conditions_to_meet){
    $object = new Foo();
}
else $object = NULL;

如果你需要多次实例化,那么将它包装在一个函数中并将参数传递给你的类。

希望这有帮助。