在调用构造函数之前,有什么方法可以设置属性? [英] Is there any way to set a property before calling a constructor?

查看:92
本文介绍了在调用构造函数之前,有什么方法可以设置属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是的,我知道应该将依赖项传递给构造函数。我不是在问编码风格,是在问或不问。

Yes, I know dependencies should be passed to the constructor. I'm not asking about coding styles or do's and dont's.

我的应用程序中的许多类都与数据库驱动程序类的实例相关。为此,我使用PHP的后期静态绑定创建了一个抽象的Factory类。此类的唯一成员是保存驾驶员参考的属性。看起来像这样:

Many of the classes in my application are tied to an instance of a database driver class. For this I've created an abstract Factory class using PHP's late static binding. The only member of this class is a property to hold the driver's reference. It looks like this:

abstract class Factory {

    static private $__instances;
    static private $__default_driver;

    protected $_driver;

    static public function getInstance ( \Database\Driver $driver = null ) {
        if ( ! isset($driver) ) {
            if ( ! isset(self::$__default_driver) ) {
                require ( \Core\Options::$database_driver[ 'path' ] );
                self::$__default_driver = new \Core\Options::$database_driver[ 'class' ]( \Core\Options::$database_options );
            }
            $driver = self::$__default_driver;
        }

        $schema = $driver->getDatabase();
        $class  = get_called_class();

        if ( ! isset(self::$__instances[ $schema ][ $class ]) ) {
            self::$__instances[ $schema ][ $class ] = new $class( $driver );
            self::$__instances[ $schema ][ $class ]->_driver = $driver;
        }

        return self::$__instances[ $schema ][ $class ];
    }
}

如您所见,当我创建一个派生类,我将驱动程序的实例传递给其构造函数。然后设置属性。如果可能的话,我想通过先设置属性然后调用构造函数来扭转这种情况。这样,派生类不需要实现构造函数,也不必担心调用父方法。

As you can see, when I create an instance of the derived class, I pass an instance of the driver to its constructor. THEN set the property. I want to reverse this, if possible, by setting the property first then call the constructor. This way a derived class doesn't need to implement a constructor or worry about calling parent methods if it does.

我已经研究了 Reflection API可以做到这一点,但是我似乎找不到任何可行的方法。我发现大多数依赖注入链接实际上都使用了构造函数。这需要在PHP 5.3上工作。

I've looked into the Reflection API to do this, but I can't seem to find anything that would work. Most Dependency Injection links I found actually use the constructor. This needs to work on PHP 5.3.

对于那些敢于做到这一点的人,在PHP 5.4中可以使用 ReflectionClass :: newInstanceWithoutConstructor()轻松完成

For those who are adament that this is not possible, It can easily be done in PHP 5.4 using ReflectionClass::newInstanceWithoutConstructor().

推荐答案

class Foo {
    public function __construct() {
        echo 'foo';
    }
}

$r = new ReflectionClass('Foo');
$o = $r->newInstanceWithoutConstructor();
$o->bar = 'baz';
$o->__construct();

从PHP 5.4开始,这是可能的。

This is possible since PHP 5.4.

但实际上:没有。就是不行。 。应始终在实例化对象时调用对象的构造函数。不会(显然),不会再迟。构造函数和对象其余部分的适当封装可确保对象始终处于一致状态。一旦使用 ReflectionClass 将其分解开来,就无法再保证对象的状态了,健全性和类型安全性便不在了。

But really: no. Just no. Don't. An object's constructor should always be called when the object is instantiated. No sooner (obviously), no later. Constructors and appropriate encapsulation of the rest of the object guarantee that the object is always in a consistent state. Once you start taking it apart using ReflectionClass no guarantees can be made anymore about the state of the object, and sanity and type safety go out the window.

由于您的年龄是5.3,所以很幸运,那里没有办法做到这一点。如果您发现自己陷入这样的困境,那说明您做错了。已经编写了完全复杂的程序,而无需欺骗PHP的对象模型来延迟构造函数的调用。

Since you're on 5.3 you're lucky that there's no way to do this there. If you find yourself backed into a corner like this, you're simply doing it wrong. Perfectly complex programs have been written without needing to trick PHP's object model into delaying constructor invocation.

这篇关于在调用构造函数之前,有什么方法可以设置属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆