views:

232

answers:

3

Hey guys!

I have a class which has a function to retrieve children elements from a database. The following code will be rather pseudo cause I want to keep it as easy as possible.

abstract class SomeHostObject extends SomeObject {

   function getChild($identifier) {
      global $database;
      $id = $database->select('Some MySQL Query');
      // that is the problem
      return ?new? ???($id);
   }

}

As you see, the class SomeHostObject is abstract and has to be extended.

The thing is that the getChild() should not return a SomeHostObject instance (not only because it can't even be instantiated) but a new instance of the class that extends SomeHostObject.

For example, if there was a class PageObject which extends SomeHostObject, the function getChild() should return a new PageObject instance with the new id.

I don't know whether to call that question 'advanced' or not but to me it's a major problem so c'mon and answer me. Right now! :D

Thanks a ton in advance!

+1  A: 

Hm, if this is good software design or not is another discussion, more then 2 levels of inheritance smell a bit imho. You should think about using composition rather then inheritance. But to focus in the technical part of the question, I would use get_class in order to get the class name of the current instance and create a new one like so:

  <?php

  class SomeObject
  {}

  abstract class SomeHostObject extends SomeObject {
     function getChild($identifier) {
        $className = get_class($this);
        return new $className($identifier);
     }
  }

  class PageObject extends SomeHostObject
  {
    private $identifier;

    public function __construct($identifier = 0)
    {
      $this->identifier = $identifier;
    }
  }

  $instance = new PageObject();
  $child = $instance->getChild(10);

  print_r($child);

This prints on my machine something like

PageObject Object ( [identifier:private] => 10 )
Max
See comment on gabriel1836's post.Yeah, I'm aware of the inheritance levels but I really need it because it's for an extensible CMS.
Daniel
+4  A: 
abstract class SomeHostObject extends SomeObject {

   function getChild($identifier) {
      global $database;
      $id = $database->select('Some MySQL Query');
      // that is the problem
      return $this->createObject($id);
   }
   abstract protected function createObject($id);

}

class PageObject extends SomeHostObject
{
  protected function createObject($id)
  {
    return new PageObject($id);
  }

}
Ewan Todd
+2  A: 

You could accomplish it with something as simple as this if the child object will be the same class as the object which calls getChild():

$class = get_class($this)

return new $class($id);
Noah Goodrich
Nice approach, but I don't think it's good for the performance… Thanks anyway!
Daniel