How to Restrict Object Instantiation to Other Classes?

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
tomcatexodus
Forum Newbie
Posts: 9
Joined: Thu Apr 08, 2010 9:42 pm

How to Restrict Object Instantiation to Other Classes?

Post by tomcatexodus »

I'm looking for a way to restrict instantiation.

If I have a class named Machine, and a class named Widget, how can I prevent the Widget class from being instantiated unless it is performed by a method in the Machine class?

I know that nested classes are not valid, but this code exemplifies the functionality I'm looking to achieve:

Code: Select all

class Machine{

    private class Widget{
        //Widget properties and methods
    }

    public function makeWidget(){
        $newWidget = new Widget();
        return $newWidget;
    }

    //Machine properties and methods

}

$myMachine = new Machine();
$myWidget = $myMachine->makeWidget(); //would work fine

$myOtherWidget = new Widget(); //would fail
How can I achieve this?
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: How to Restrict Object Instantiation to Other Classes?

Post by requinix »

First: realize that PHP does not have a perfect OOP implementation. You'll have to take a hit someplace.
Second: there is a way to figure out what just happened during execution, but unless you're looking for debugging purposes you shouldn't use it.

What I would do:
Give the Widget class a constructor that takes a Machine as an argument. It then asks the Machine for whatever information it needs to construct itself.

Code: Select all

public function __construct(Machine $machine) {
    // ...
}
Naturally the Machine class has a function to return a new Widget.

Code: Select all

public function getWidget() {
    return new Widget($this);
}
Yes, you could instantiate the Widget without using Machine::getWidget - that's the aforementioned hit you're taking. It's a good design so don't toss the idea out because it isn't exactly what you want.
Post Reply