Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: PHP OOP

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>
<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 13-Feb-13 5:59am
Comments
Sergey Alexandrovich Kryukov at 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
Peter Trumbull at 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.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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.
  Permalink  
Comments
Peter Trumbull at 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_ at 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
Peter Trumbull at 14-Feb-13 6:09am
   
OK.
 
But can you answer my questions?
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

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.
  Permalink  
Comments
Peter Trumbull at 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)

  Print Answers RSS
0 OriginalGriff 195
1 ProgramFOX 130
2 Maciej Los 105
3 Sergey Alexandrovich Kryukov 105
4 Afzaal Ahmad Zeeshan 82
0 OriginalGriff 6,564
1 Sergey Alexandrovich Kryukov 6,048
2 DamithSL 5,228
3 Manas Bhardwaj 4,717
4 Maciej Los 4,150


Advertise | Privacy | Mobile
Web03 | 2.8.1411022.1 | Last Updated 14 Feb 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100