This is an occasion where interfaces can really shine. To extend on NogDog's example, all we really care about is that the object being added can move in some way. So we can isolate that behaviour using an interface.
interface IMovable
{
public function move( $x, $y );
}
class Planet extends Spherical implements IMovable
{
public function move( $x, $y )
{
$this->orbit( $x, $y );
}
}
class Probe extends ManMade implements IMovable
{
public function move( $x, $y )
{
$this->thrust( $x, $y );
}
}
Now all the Motion class cares about is that the object implements the IMovable interface. It's useful to use an interface rather than an abstract class, because we are only requiring that a particular behaviour exists (move(), in this case). This leaves our 1 shot of inheritance to be used for something more specific.
class Motion
{
private $moveables = array();
public function add( IMovable $obj )
{
$this->moveables[] = $obj;
return true;
}
public function move( $x, $y )
{
foreach( $this->moveables as $obj )
{
$obj->move( $x, $y );
}
}
}
$motion = new Motion;
$motion->add( new Probe );
$motion->add( new Planet );
$motion->move( 1, 2 );
Having said all of this, it is unlikely that you would want to work this way in your real-life problem. If you are envisioning a website application to manage courses and students you will only ever be dealing with a few instances of objects. HTTP being a stateless protocol tends to mean not much is kept in memory at any given time, rather things are loaded from and written to a database as and when they are needed.