SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Member
    Join Date
    Sep 2003
    Location
    sydney, Australia
    Posts
    8
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Creating object of a class and return the subclass

    Hi everyone,
    I am trying to do the following, but it doesn't seem to work.


    PHP Code:
    class Item {
        
    // Constructor:
        
    function Item($type) {
            if(
    $type == 'question'
                return new 
    Question();

            elseif(
    $type == 'section')
                return new 
    Section();
        }
    }

    class 
    Question extends Item {
        function 
    Question() {
            echo 
    'a new Question is created';
        }
        function 
    display_me() {
            echo 
    'This is Question';
        }
    }

    class 
    Section extends Item {
        function 
    Section() {
            echo 
    'a new Section is created';
        }
        function 
    display_me() {
            echo 
    'This is Section';
        }
    }


    $newItem = new Item($_POST['type']);
    $newItem->display_me(); 
    The output of the above is:
    'Call to undefined function: display_me()'

    Can anybody help me trying to achieve this?
    What I'm trying to do is create an object based on the given type (either say, Question or Section).

    But since Question and Section are both of type Item, I 'd like to deal only with class Item. So in the script, I should only have those 2 lines:

    $newItem = new Item($_POST['type']);
    $newItem->display_me();

    without even care whether it's a Question or a Section.

    Is there a way around this? or does PHP even support this sort of thing?

    Any help would be appreciated...

  2. #2
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Remember that objects of the parent class don't herite (sp?) the methods of the child class. It's the other way round. In your example, you need to create the object newsItem as an instance of either the Section class or the Question class. display_me() is not available to direct instances of the Item class.

    Furthermore, you want to return an object in your Item class. The right syntax is "return new Question;". You put "return new Question();".

    Hope this helps.

  3. #3
    La la la la la bronze trophy lieut_data's Avatar
    Join Date
    Jun 2003
    Location
    Waterloo, ON
    Posts
    1,517
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by marcellusc
    The output of the above is:
    'Call to undefined function: display_me()'

    Can anybody help me trying to achieve this?
    The new operator always returns an instance of the object to be instatiated. It completely ignores the return value of the constructor (which there shouldn't be, anyway)

    Thus, by instatiating an object of type Item, you are limited to accessing only members and functions of that object:

    PHP Code:
    $newItem = new Item($_POST['type']); 
    Since Item doesn't define any funtions (besides the constructor), you can do little with the Item class.

    Instead, I believe a solution to your problem would be to keep a reference of the needed object inside the Item class:

    PHP Code:
    class Item {
       var 
    obj;

        
    // Constructor:
        
    function Item($type) {
            switch (
    $type) {
                case 
    'question':
                   
    $this->obj = new Question();
                   break;
                case 
    'section':
                   
    $this->obj = new Section();
                   break;
            }
        }

    Of course, in order to be able to instatiate an object of either class, they will need to be defined above the Item class.

    Nex, you will need to define the functions that the children classes use, inside Item (for instances of the Item class to be callable):

    PHP Code:
    class Item {
       
    //Constructor...

       
    function display_me() { 
          
    $this->obj->display_me();
       }

    I believe that you are trying to achieve something like 'reverse-inheritance' -- which doesn't work. Parents can't be expected to have all the features of their children, but children most likely have all (& more) of their parent's features.
    My name is Steve, and I'm a super-villian.

  4. #4
    La la la la la bronze trophy lieut_data's Avatar
    Join Date
    Jun 2003
    Location
    Waterloo, ON
    Posts
    1,517
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DarkAngelBGE
    Furthermore, you want to return an object in your Item class. The right syntax is "return new Question;". You put "return new Question();".
    Actually, either one will work -- empty parentheses simply mean no arguments, as do no parentheses mean no arguments.

    Edit:


    Wow, I've never written with such poor grammar!
    My name is Steve, and I'm a super-villian.

  5. #5
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually, either one will work -- empty parentheses simply mean no arguments, as do no parentheses mean no arguments.
    Thanks, for the clear up.

  6. #6
    SitePoint Member
    Join Date
    Sep 2003
    Location
    sydney, Australia
    Posts
    8
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    lieut_data, that's an excellent idea... thanks for that.

    I've also found another alternative way to do this....

    PHP Code:

    class Item 
        var 
    $description// all subclasses should have this variable.
        // Constructor: 
        
    function Item($type) { 
            if(
    $type == 'question'
                
    $this = new Question();

            elseif(
    $type == 'section'
                
    $this = new Section(); 

            
    // set the common variable among all subclasses:
            
    $this->description 'This is an Item....';
        } 
        function 
    display_me() { 
            
    // Interface
        




    class 
    Question extends Item 
        function 
    Question() { 
        } 
        function 
    display_me() { 
            echo 
    $this->description;
            echo 
    'This is a Question, a subclass of Item'
        } 


    class 
    Section extends Item 
        function 
    Section() { 
        } 
        function 
    display_me() { 
            echo 
    $this->description;
            echo 
    'This is a Section, a subclass of Item'
        } 

    Therefore, if I do this:
    $newItem = new Item('question');
    $newItem->display_me();

    Output is:
    Code:
    This is an Item....
    This is a Question, a subclass of Item
    Or
    $newItem = new Item(section);
    $newItem->display_me();

    Output will be:
    Code:
    This is an Item....
    This is a Section, a subclass of Item

    This way also achieves the same thing as the technique you demonstrated above. But instead of having an object of class Question or Section inside the object Item, the Item itself becomes the Question or Section... but still preserves the commonalities of the parent class Item (in the example above, both classes still have access to $description) If that makes sense at all...

    What do you think of this approach?


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •