Click here to Skip to main content
15,886,733 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:


Hi,
I need your help. If I add the drums to the cymbals that already belong to drums then I create a circular reference. When calling getDescription() a line like this can crash a Web Server. I want to safeguard against such mistakes. My strategy would be to check during the add() method to see whether the instrument being added already contains a reference to the one calling the method.My pseudo-code is:


  1. Check if drums has children;
  2. If has children then compare drums with cymbals:
  3. If are equals then return true else return false;


My questions are:
  1. Is it correct my logic/pseudo-code?
  2. To transale this pseudo-code to PHP, is it good idea to create a recursive method or interactive method?
  3. There is another way to check a circular reference? If so, please tell me!

HTML
<html>
<body>
<head>
<style>
body{ font:12px Verdana, Geneva, sans-serif; font-weight:bold}
td{ font:11px Verdana, Geneva, sans-serif;}
</style>
</head>
<?php
abstract class AbstractInstrument{
	
	private $name;
	private $category;
	private $instruments = array();
	
	public function add(AbstractInstrument $instrument){
		array_push($this->instruments, $instrument);	
	}
	
	public function remove(AbstractInstrument $instrument){
		array_pop($this->instruments, $instrument);
	}
	
	public function hasChildren(){
		return (bool) (count($this->instruments) > 0);
	}
	
	public function getChild($i){
		return $instruments[$i];
	}
	
	public function getDescription(){
		echo "- one ".$this->getName();
		if($this->hasChildren()){
			echo " which includes:<br>";
			foreach($this->instruments as $instrument){
				echo "<table cellspacing=\"5\" border=\"0\"><tr><td>   </td><td>-";
				$instrument->getDescription();
				echo "</td></tr></table>";
			}
		}
	}
	
	public function setName($name){
		$this->name=$name;
	}
	
	public function getName(){
		return $this->name;
	}
	
	public function setCategory($category){
		$this->category=$category;
	}
	
	public function getCategory(){
		return $this->category;
	}
}

class Guitar extends AbstractInstrument{
	function __construct($name){
		parent::setName($name);
		parent::setCategory("guitars");
	}
}

class DrumSet extends AbstractInstrument{
	function __construct($name){
		parent::setName($name);
		parent::setCategory("drums");
	}
}

class SnareDrum extends AbstractInstrument{
	function __construct($name){
		parent::setName($name);
		parent::setCategory("snare drums");
	}
}

class BaseDrum extends AbstractInstrument{
	function __construct($name){
		parent::setName($name);
		parent::setCategory("base drums");
	}
}

class Cymbal extends AbstractInstrument{
	function __construct($name){
		parent::setName($name);
		parent::setCategory("cymbals");
	}
}

$drums = new DrumSet("tama maple set");
$drums->add(new SnareDrum("snare drum"));
$drums->add(new BaseDrum("large bass drum"));

$cymbals = new Cymbal("zildjian cymbal set");
$cymbals->add(new Cymbal("small crash"));
$cymbals->add(new Cymbal("large high hat"));

$drums->add($cymbals);
//$cymbals->add($drums); //Uncomment this and then it will show an error!!

$guitar = new Guitar("gibson les paul");
echo "List of instruments: <p>";
$drums->getDescription();
$guitar->getDescription();
?>
</body>
</html>
Posted
Comments
Sergey Alexandrovich Kryukov 13-Feb-13 13:41pm    
Before we continue, can you explain what's wrong in circular references? They are pretty much a commonplace, can be found anywhere. What's wrong?
—SA
[no name] 13-Feb-13 16:46pm    
I think a circular reference is a mistake very serious. Please copy code, uncomment "//$cymbals->add($drums)" and test! This will origin a error. I want prevent this mistake.

Your $drums is actually a drum set, not a collection of drums, isn't it?

So should you not be adding each cymbal to that collection rather than adding cymbal to a collection of cymbals then adding that collection to the drum set?

So I would have a Drum Set to which I add each drum and each cymbal(or add a collection of drums and a collection of cymbal)

If Cymbals needs a reference to the Drum Kit then all good - the collection of Cymbals' parent would be the drum kit.
 
Share this answer
 
Comments
[no name] 14-Feb-13 5:38am    
My $drums is actually a drum set, not a collection of drums.

No. I should not be adding drums to the cymbals that already belongs to drums! This origin a circular reference.

A drum set is a composite of (1 or more)drum(s) and (1 or more)cymbal(s).

My questions are:
1)Is it correct my logic/pseudo-code?
2)To transale this pseudo-code to PHP, is it good idea to create a recursive method or interactive method?
3)There is another way to check a circular reference? If so, please tell me!
_Maxxx_ 14-Feb-13 6:02am    
You say you shouldn't be adding drums to the cymbals - then surely the answer is "then don't"
The way you are setting up our drum$ is that it is a collection that contain individual drums plus a collection of cymbals. M
[no name] 14-Feb-13 6:09am    
OK.

But can you answer my questions?
It is not possible to answer your question sensibly;

Your pseudo code will always return true given the info you have given.

if you can add a drum kit to a cymbal, could you also add a cymbal to a cymbal, or a drum to a cymbal? Your Cymbal object seems to act both as an individual and a collection of cymbals (there is no Cymbalset class) so I cannot deduce what your intentions may be.

If you talk abstractly of collections that can hold collections and you do not want to add collection a to collection b if some object already in collection b contains collection a, then you would need to traverse the entire tree every time you want to add to any collection; If I had to do it I would do it recursively - but as I said earlier, i wouldn't do it like this in the first place.
 
Share this answer
 
Comments
[no name] 14-Feb-13 6:27am    
Thanks for your help anyway.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900