How to Restrict Object Instantiation to Other Classes?
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:
PHP Code:
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?
Re: How to Restrict Object Instantiation to Other Classes?
we can use the debug_backtrace() function to figure out which object called a class (if any), and so something like this should work for you:
PHP Code:
<?php
class Widget {
private $_name;
public function __construct($name){
$trace = debug_backtrace();
//make sure that an instance of Machine called us
if(!isset($trace[1]) || (!$trace[1]['object'] instanceof Machine)){
trigger_error("Widget class can only be instantiated from within the Machine class", E_USER_ERROR);
//or throw an exception
}else{
$this->_name = $name;
}
}
public function __toString(){
return $this->_name;
}
}
class Machine {
public function __construct(){ }
public function makeWidget(){
$widget = new Widget("myNewWidget");
return $widget;
}
}
echo "make a new widget object from machine object:\n";
$m = new Machine;
echo $m->makeWidget(); //will succeed and return the widget name
echo "\n\n\n";
echo "make a new widget object:\n";
echo new Widget("someWidget"); //will cause a fatal error
?>
this is probably not the ideal way of doing it (as other languages have a more direct way of finding out what the parent class is [parent not meaning inheritance here]), but I don't know of any other way for you to get what you want! it should give you the functionality that you're looking for.
Re: How to Restrict Object Instantiation to Other Classes?
Thanks Kows, seems that this is the best resolution. For questions like this, I use multiple forums, so for discussion's sake, here's what some other people had to say:
http://forums.devshed.com/php-develo...es-693799.html
http://forums.devnetwork.net/viewtopic.php?f=1&t=115183
I'd mark this thread resolved, but I certainly want to see if any other viable options exist.
Re: How to Restrict Object Instantiation to Other Classes?
while I understand what that one person is saying when they mentioned that it "should be used for debugging," (assuming they were even talking about debug_backtrace) the function can serve purposes other than just debugging, too. and I don't think it's that messy.
but I don't like the first solution that was offered, though the one that uses type hinting would be okay in some situations.
as mentioned by the posts on those forums, PHP doesn't implement a perfect object model and doesn't "directly" support what you're trying to do. I'm not sure any other viable options do exist, but I'd personally like to see what penagate or visualAd have to say about this.
Re: How to Restrict Object Instantiation to Other Classes?
Quote:
Originally Posted by
kows
as mentioned by the posts on those forums, PHP doesn't implement a perfect object model and doesn't "directly" support what you're trying to do.
Unfortunately so, but I think the ends of your approach justifies it's means, in it mimics closely what I'm trying to achieve. Patiently awaiting nested classes.
Quote:
Originally Posted by
kows
I'm not sure any other viable options do exist, but I'd personally like to see what penagate or visualAd have to say about this.
Agreed.
Re: How to Restrict Object Instantiation to Other Classes?
I looked at this a few years ago. The debug_backtrace function was the only method I came up with back then also. Another method could be to share a token which is known only to the Machine and Widget classes but that requires some degree of physical separation between them and any "foreign" classes which oughtn't to be able to instantiate a Widget.
Is this for a plugin system?
Re: How to Restrict Object Instantiation to Other Classes?
(Old post yes, but the question is still relevant)
I'm not sure what you meant by plug in system, but it is for a component that can be used in an MVC framework, the Controller/View.
After much searching, debug_backtrace() still holds the title, despite it's "messiness". Could you or anyone elaborate on how I'd implement a token as such? The Widget and Machine classes should not extend one another.
As of the moment, this is the class hierarchy:
PHP Code:
abstract class Supervisor{ //aka Machine
private static $isInitialized = false;
private static $params = array(); //global properties
public static function init($args){
//set params and other stuff
self::$isInitialized = true;
}
public static function makeAlpha($args){
if(self::$isInitialized){
return new AlphaWidget($args);
}
}
}
abstract class WidgetBase{
//inheritable qualities
public function makeBeta($args){
return new BetaWidget($args);
}
public function makeGamma($args){
return new GammaWidget($args);
}
public function makeDelta(...
.
.
.
}
class AlphaWidget extends WidetBase{
//Alpha specific properties/methods
public function __construct($args){
//IF NOT CALLED FROM SUPERVISOR THROW EXCEPTION
//do stuff
}
}
class BetaWidget extends WidgetBase{
//Beta specific properties/methods
protected function __construct($args){
//do stuff
}
}
class GammaWidget extends WidgetBase{
//Gamma specific properties/methods
.
.
.