Constructor gap

Is there a way to prevent the creation of an object inside its constructor so that:

$object = new Foo(); echo $object; // outputs: NULL 
+6
oop php
source share
5 answers

No impossible; The new keyword always returns an instance of the specified class, regardless of what you are trying to return from the constructor. This is due to the fact that by the time you created your constructor PHP had already completed the allocation of memory for a new object. In other words, an object already exists at this point (otherwise there is no object for which you can invoke the constructor at all).

Instead, you can create errors or throw exceptions from the constructor and handle them accordingly.

 class Foo { public function __construct() { throw new Exception('Could not finish constructing'); } } try { $object = new Foo(); } catch (Exception $e) { echo $e->getMessage(); } 
+14
source share

Impossible, but you can proxy the creation .

 <?php class Foo { private function __construct() {} static function factory($create=False) { if ($create) { return new Foo; } } } 
+3
source share

Just throw an exception:

 throw new Exception('thou shalt not be born!'); 
+2
source share

You can implement a factory to create an object for you. If you are using PHP 5.3.0+, then you will have access to a function called Late Static Binding that will simplify this.

 <?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\'ma ' . 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); ?> 

If you use a version of PHP prior to 5.3.0, then the situation becomes a little more complicated, since late static binding and get_called_class () are not available. However, PHP 5 does support reflection, and you can use it to emulate late static bindings. Alternatively, you can implement a separate factory class and pass an argument to it that indicates which object you want to initialize.

Another approach is to force your constructor to throw an exception if it fails, and handle it with a catch block. However, this method can get a hairy look if you do it a lot, and should be used only when you usually expect the creation of the object to succeed (in other words, if the creation failure is an exceptional circumstance).

The factory approach has additional advantages, for example, it may contain a cache of objects that you have already created, and if you try to create the same object twice, it will simply give you a link to an already initialized object for creating a new one. This eliminates the memory and processing inherent problems of creating an object, especially if the creation involves a time-consuming task, such as a complex SQL query

+1
source share

If you are trying to stop an object from being instantiated depending on several conditions, then why not create a condition before you hit PHP new and instantiate the class?

What I mean, let's say in your example:

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

You can wrap it in a function that performs validation for you or just an if statement if you are only going to instantiate the class once.

Like this:

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

if you need to create multiple instances, then wrap them in a function and pass parameters to your class.

Hope this helps.

0
source share

All Articles