Constructor Trait?
Hi, Would it be a good idea to have a trait that prevents the class constructor(s) from running more than once? I would be more than willing to code this up, I just have no idea what to call it.
Probably DontInstantiate?
So I've been rattling this one around in my brain, and I don't see how this is possible without setting a class property?
Is it not possible to add a private ctor?
I think we are talking about addressing two different things here.
Yes private constructors can be added.
I was referring to preventing a class constructor from executing more than once.
I was referring to preventing a class constructor from executing more than once.
Ok, that is something I misread while scanning the notifications, sorry.
I think it can be done, but it's hard to do so without introducing more state in a class.
I would suggest going the easy way first: add a private property that is also marked @internal and you should be OK for now.
As for making it work with generic constructors, it becomes really tricky, but I've done it in ocramius/proxy-manager, and can be done through https://github.com/Ocramius/ProxyManager/blob/f65ae0f9dcbdd9d6ad3abb721a9e09c3d7d868a4/examples/access-interceptor-scope-localizer.php
Here is how I see it going down. This is just pseudo code... Exceptions will be replaced with proper ones once I start coding.
@Ocramius - You are by far a better PHP programmer than me, so I wanted to check to see if this is what you had in mind?
<?php
declare(strict_types=1);
namespace Dont;
trait DontInstantiateTwice
{
/**
* constructorHasInited
* Has the constructor inited?
*
* @var bool
* @internal
*/
private $constructorHasInited = false;
private function initConstructor(): void
{
if ($this->constructorHasInited===true)
{
throw Exception('reserved for future message');
}
$this->constructorHasInited = true;
}
}
Pseudo Usage
<?php
use Dont\DontInstantiateTwice;
class Foo
{
use DontInstantiateTwice;
/**
* __construct
* Do some busy work
* ...
*
* @throws Exception - When the __construct is called more than once
* per instantiated object
*/
public function __construct()
{
//doing some busy work
//...
$this->initConstructor();
}
}
$this->initConstructor(); is not really defensive, since you can easily forget to call it.
Agreed