How to instantiate a child class using its parent factory in __construct

I have a class A that needs to be created using other objects with multiple objects

class A{ function __construct(new X(), new Y(), new Z()){ $this->foo = 'foo'; } } 

To save me the trouble of creating this class, I created a factory for this class.

 class A_Factory{ public static function create_A(){ return new A(new X(), new Y(), new Z()); } } 

I have class B with an extension of class A. My problem is that I cannot figure out how to instantiate class A in class B in order to access the foo property.

It was natural for me to try:

 class B extends A{ function __construct(){ A_Factory::create_A(); } } 

but it generates a notification error when trying to access the properties of object A:

 Undefined property: A::$foo 

How can I use class A factory to instantiate A easily in my child classes? Thanks.

+5
source share
2 answers

You are trying to use A_Factory::create_A() in the same way you would use parent::__construct() . However, these are two completely different challenges.

Parent :: __ construct ()

parent allowed by A The current $this object is an instance of A (because each instance of B also an instance of A due to inheritance). In this case, the call is not a static call , although the :: operator is used ( $this remains the same).

The following code works:

(assuming foo not private )

 class B extends A { function __construct() { parent::__construct(new X, new Y, new Z); echo $this->foo; } } 

This also works:

 class B extends A { function __construct() { A::__construct(new X, new Y, new Z); echo $this->foo; } } 

Factory

A_Factory::createA() is a static call because A_Factory not in the inheritance tree of B In addition, A_Factory creates and returns a new instance of A So, once this was called, you have two different objects: $this is still an immutable instance of B , and you created another instance of A without assigning it to any variable.

A possible approach is to move the factory method to A

This will work:

 class A { function __construct(X $x, Y $y, Z $z) { $this->foo = 'foo'; } public static function create() { return new static (new X, new Y, new Z); } } class B extends A { } // Instantiating: $a = A::create(); $b = B::create(); 

This uses late static binding with the static . static resolves the class name of the called class, so it is A in A::create() and B in B::create() .

Note the difference in self , which always resolves the class in which the method is declared (in which case it will always be A )

+4
source

You have a slight misunderstanding about how inheritance works. I think because of this line in constructor B:

 A_Factory::create_A(); 

A parent is not a property of a child class. If you create new A([...]) inside constructor B, it will be another class completely separate from your B, and there is no way to β€œmerge” it with an existing object. To build a parent from a child class, you must do this:

 class B { function __construct() { parent:__construct(new X(),new Y(),new Z()); } } 

Here is a way to create your classes using factory and some hint type. Notice how I moved the different new XYZ() so that they are not in your class constructors. Naked news in designers is considered bad practice, as they hide the dependencies of your classes.

 class B_Factory { public static function create_B(X $X,Y $Y, Z $Z) { return new B($X, $Y, $Z); } } class X {} class Y {} class Z {} class A { public function __construct(X $X, Y $Y, Z $Z) { $this->foo = "foo"; } } class B extends A { public function __construct(X $X, Y $Y, Z $Z) { parent::__construct($X,$Y,$Z); } } $B = B_Factory::create_B(new X(), new Y(), new Z()); var_dump($B->foo); 

The real answer is : you want your factory to be a container for dependency injection like Auryn , and using type hints your classes will be recursively created with their dependencies using reflection .

in your case (adapted from the example in auryn github repo):

 class X {} class Y {} class Z {} class A { public function __construct(X $X, Y $Y, Z $Z) { $this->foo = "foo"; } } class B extends A { public function __construct(X $X, Y $Y, Z $Z) { parent::__construct($X, $Y, $Z); } } $injector = new Auryn\Injector; $B = $injector->make('B'); var_dump($B->foo); 

Using reflection, Auryn can recursively understand what components your classes need, instantiate them, and pass them to class constructors.

+3
source

All Articles