Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constructor Trait? #27

Open
waknauss opened this issue Nov 27, 2020 · 8 comments
Open

Constructor Trait? #27

waknauss opened this issue Nov 27, 2020 · 8 comments

Comments

@waknauss
Copy link

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.

@Ocramius
Copy link
Member

Probably DontInstantiate?

@waknauss
Copy link
Author

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?

@Ocramius
Copy link
Member

Is it not possible to add a private ctor?

@waknauss
Copy link
Author

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.

@Ocramius
Copy link
Member

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

@waknauss
Copy link
Author

waknauss commented Dec 1, 2020

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();
    }
}

@vudaltsov
Copy link
Contributor

$this->initConstructor(); is not really defensive, since you can easily forget to call it.

@Ocramius
Copy link
Member

Ocramius commented Feb 8, 2021

Agreed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants