I'm making a templating system where I instantiate each tag using a foreach loop. The issue is that some of the tags rely on each other so, I'm wondering how to get around that ordering from the looping.
Here's an example:
Class A {
public $width;
__construct() {
$this->width = $B->width; // Undefined! Or atleast not set yet..
}
}
Class B {
public $width;
__construct() {
$this->width = "500px";
}
__tostring() {
return "Hello World!";
}
}
Template.php
$tags = array("A", "B");
foreach ($tags as $tag) {
$TagObj[$tag] = new $tag();
}
echo $TagObj['A']->width; // Nadamundo!
EDIT: Ok just to clarify.. My main problem is that Class A relies on Class B, but class A is instantiated before class B, so therefore width has not yet been defined in class B. I am looking for a good way to make sure all the classes are loaded for everyone allowing the interdependencies to exist. For the future, please don't consider any syntax errors.. I just made up this example on the spot. Also assume that I have access to class B from class A after class B gets instantiated.
I know this has applications elsewhere and I'm sure this has been solved before, if someone could开发者_开发百科 enlighten me or point me in the right direction that'd be great!
Thanks! Matt Mueler
The easiest way will probably be by making a second pass over the array of tag objects once they've all been instantiated, and calling some standard method (see template method pattern e.g. http://java.dzone.com/articles/design-patterns-template-method ) on each e.g.
$tags = array("A", "B");
foreach ($tags as $tag) {
$TagObj[$tag] = new $tag();
}
foreach (array_keys($TagObj) as $tagName) {
$TagObj[$tagName]->resolveDependencies($TagObj);
}
How resolveDependencies is implemented will vary from class to class.
Where does this $B instance in A::construct() come from? It's not there in scope.
Possible solitions:
1) Static values:
class B {
static $width = '500px';
...
class A {
function construct(){
$this->width = B::$width;
}
2) Static functions:
class B {
static function width(){
return '500px';
...
class A {
function construct(){
$this->width = B::width();
}
3) Just in time factorymethod (or object if you need one), if you need objects
function getTag($name){
global $TagObj;
if(!isset($TagObj[$name]) && class_exists($name)){
$TagObj[$name] = new $name();
}
return $TagObj[$name];
}
class A {
function construct(){
$this->width = getTag('B')->width();
}
....
$tags = array("A", "B");
foreach ($tags as $tag) {
$TagObj[$tag] = getTag($tag);
}
And if you want a change in B to reflect in A you could always use references instead of assignments. All this of course expects the class definition to be available, define an __autoload() if not, or include them all beforehand.
You are missing width()
method in B
class that you are calling in A
class $this->width = $B->width();
(and you should include or sort of use inheritance to use B class in A class)
Class B {
private $width;
__construct() {
$this->width = "500px";
}
__tostring() {
return "Hello World!";
}
function width() {
return $this->width;
}
}
As for ordering, you should be more specific.
精彩评论