有没有什么办法调用构造函数之前设置的属性?(Is there any way to set a pr

2019-10-20 01:58发布

是的,我知道的依赖应该传递给构造。 我不要求有关的编码风格或做的和不要的。

许多在我的应用程序的类都依赖于数据库驱动程序类的一个实例。 为此,我已经创建了使用PHP的后期静态绑定一个抽象工厂类。 这个类的唯一成员是保持驾驶员的参考属性。 它看起来像这样:

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 ];
    }
}

正如你所看到的,当我创建派生类的实例,我通过驱动程序的实例给它的构造。 然后设置该属性。 我想如果可能扭转这种,通过设置属性第一,然后调用构造函数。 这样,派生类并不需要实现一个构造函数或担心调用父方法,如果它。

我已经研究过的Reflection API来做到这一点,但我似乎无法找到任何会工作。 大多数Dependency Injection我发现链接实际使用的构造函数。 这需要在PHP 5.3的工作。

对于那些谁是adament,这是不可能的, 它可以很容易地在PHP 5.4完成使用ReflectionClass::newInstanceWithoutConstructor()

Answer 1:

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

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

这是可能的,因为PHP 5.4。

但真正做到:无。 就是不行。 别。 当对象实例化一个对象的构造应该总是被调用。 没有快(显然),不迟。 构造函数和对象保障对象是始终一致的状态的其他适当的封装。 一旦你开始把它拆开使用ReflectionClass没有保证可以再对该对象的状态,和理智和类型安全走出去的窗口。

既然你是在5.3你是幸运的,有没有办法做到这一点那里。 如果你发现自己被逼到这样的一个角落里,你只是做错了。 完美复杂的程序已被写入,而无需欺骗PHP的对象模型到延迟构造函数调用。



Answer 2:

“我知道的依赖应该传递到构造”,其中依赖性是由一个覆盖构造继承的,不正确的,在情况下,使用它是一个坏主意。

在这种情况下,类甚至可能不使用构造,这意味着类持有是其依赖关系和方法的对象的生命周期中视为静态,然后无状态的唯一国家。

这是在Symfony2中非常普遍,通过DI加载某些服务不包括传递给构造函数的参数,或者如果是这样,那么扩展必须兼容。



Answer 3:

你不能设置一个对象,尚不存在的价值,你需要实例化对象,然后通过将必要的参数构造函数和里面你必须使用参数来初始化对象的构造进行初始化。



文章来源: Is there any way to set a property before calling a constructor?