SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    SitePoint Member
    Join Date
    Feb 2005
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    class extending, inheritance, and references

    Hi All,

    I've been trying to wrap my head around this question, but I can't seem to get it, even after rereading the excellent OOP tutorial here: http://www.sitepoint.com/article/object-oriented-php

    I'm trying to get a child class to inherit the values of its' parent. Here's a simple bit of code:

    PHP Code:
    <?php
    error_reporting
    (E_ALL);

    class 
    mainClass {
        var 
    $mainVar '1234'// explicitly set the value
        
        
    function mainClass$newValue ) {
            
    $this->mainVar 'abcd'// now change the value
            
    return true;
        }
        
        function 
    returnMainVar() {
            return 
    $this->mainVar// which value does it return, 1234 or abcd?
        
    }
    }

    class 
    subClass extends mainClass {
        
        function 
    subClass() {
            return 
    true;
        }
        
        function 
    showVar() {
            return 
    parent::returnMainVar();
        }
        
    }

    $main = &new mainClass();
    $sub = &new subClass();

    echo 
    'Printing variable display from main class: ' $main->returnMainVar();
    echo 
    '<br>';
    echo 
    'Printing variable display from sub class: ' $sub->showVar();

    ?>
    The value for $mainVar is '1234', then I change it to 'abcd' in the mainClass() method. However, when I try to access $mainVar from within the subClass, it switches back to the original value of '1234', not the NEW value of 'abcd'.

    I think my mistake is that I'm not referencing the call, instead I'm re-reading the inital value for $mainVar, but I've tried countless combinations blindly, and none of them seem to work.

    How do I get the subClass to access the new mainVar variable value, instead of the original one?

    Thanks!

  2. #2
    SitePoint Zealot
    Join Date
    May 2004
    Posts
    142
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    When you instantiate a class, the constructor of its parent class (if it has one) is not automatically run (only the constructor of the instatiated class); you must explicitely call the method from the child class with parentClass::parentClass().

    Since the changing of the variable is occurring in the parent constructor, this will only take place is the parent constructor is explicitely called (which it isn't, as stated above).

    What you need is to call the parent constructor from within the child constructor (or another child method), like so:

    PHP Code:

    class subClass extends mainClass {
        
        function 
    subClass($someValue) {
            
    parent::mainClass($someValue);  //calling parent constructor here
            
    return true;
        }
        
        function 
    showVar() {
            return 
    parent::returnMainVar();
        }
        

    Make that change to your subClass; it should now work as you want. Note that the parameter ($someValue) passed to the parent constructor has to be passed to the child constructor first.

  3. #3
    SitePoint Member
    Join Date
    Feb 2005
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the quick reply! Your answer makes perfect sense, and brings to light possible more serious problems... I may have designed my application badly:

    I have a main() class, in which I initialize my application (for example, I detect the location of a settings file). Now I have the location of the file, say, myConfigFile set correctly in the main() class. I then need to access the value of myConfigFile inside the child classes.

    How would I do this? Or did I <gulp> approach this with bad OOP design?

  4. #4
    SitePoint Member
    Join Date
    Feb 2005
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    By the way, it can be done like this...

    PHP Code:
    <?php
    error_reporting
    (E_ALL);

    class 
    mainClass {
        var 
    $mainVar '1234'// explicitly set the value
        
        
    function mainClass() {
            
    $this->mainVar 'abcd'// now change the value
            
    return true;
        }
        
        function 
    returnMainVar() {
            return 
    $this->mainVar// which value does it return, 1234 or abcd?
        
    }
    }

    class 
    subClass extends mainClass {
        
        function 
    subClass$main ) {
            
    $this->mainVar $main->mainVar;
            return 
    true;
        }
        
        function 
    showVar() {
            return 
    $this->mainVar;
        }
        
    }

    $main = &new mainClass();
    $sub = &new subClass$main );

    echo 
    'Printing variable display from main class: ' $main->returnMainVar();
    echo 
    '<br>';
    echo 
    'Printing variable display from sub class: ' $sub->showVar();

    ?>
    This is straight from the article. I'm passing $main to subClass and accessing the instance from there. This feels really inefficient... I'm eager to hear anyone's thoughts though.

  5. #5
    SitePoint Evangelist
    Join Date
    May 2004
    Location
    New Jersey, USA
    Posts
    567
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dlst
    I have a main() class, in which I initialize my application (for example, I detect the location of a settings file). Now I have the location of the file, say, myConfigFile set correctly in the main() class. I then need to access the value of myConfigFile inside the child classes.
    Yeah, this sounds like it might be bad design.

    Do you need to get the variable, or do you need to do something with it?

    Is your subclass really a specialization of the main class, or are you substituting "IS-A" instead of "HAS-A" (inheritance instead of composition)?

    When you talk about accessing your config file, the first thing that springs to mind is that you might be trying to create a "class with a bunch of useful methods inside" which is known as a "God class".

    Alternatively, perhaps you should factor the configuration out to a separate class, so that you can "tell" your configuration class to fetch you information, rather than "ask" ing for the filepath so you can look it up yourself.

    How would I do this? Or did I <gulp> approach this with bad OOP design?
    Assuming that inheritance is the right way to go (see above) you must keep in mind that PHP does not automatically invoke parent methods. You have to invoke the parent constructor, etc., yourself if and when you want them invoked.

    So one solution generalizes what has already been given to you.

    Another solution is to build in an "accessor" method that returns the filepath of the config file -- you'll inherit the method and probably never override it.

    Code:
        function some_method($arg1, $arg2)
        {
      	$config_file = $this->get_config_file();
      	// ...
        }
    =Austin

  6. #6
    SitePoint Member
    Join Date
    Feb 2005
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So a "god class" is bad? I was thinking about the parent/child relationship as a cascading one... so that the child has access to objects and methods in the parent.

    It feels to me like this is only partly true. Back to my original example (and the original question, forget settings files, it was just an example):

    What is the best way for a child class to access the _changed_ values of objects in it's parent?

  7. #7
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dlst
    By the way, it can be done like this...
    Extending AND aggregating would be quite a strange thing to do. Usually it's one or the other. (someone will probably come up with a clever example now I've said that).

    Quote Originally Posted by dlst
    What is the best way for a child class to access the _changed_ values of objects in it's parent?
    A derived class, and it's parent class, are really just one big class. Child methods or properties will overide those defined in the parent. Anything left can be accessed in child methods as normal with "$this->foo".

    As mentioned previously, use inheritance sparingly.

  8. #8
    SitePoint Evangelist
    Join Date
    May 2004
    Location
    New Jersey, USA
    Posts
    567
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dlst
    So a "god class" is bad?
    Indeed. If you've got a "bunch of useful stuff", you don't really have a class.

    I was thinking about the parent/child relationship as a cascading one... so that the child has access to objects and methods in the parent.
    That is exactly true. A child class is a subtle variation of its parent. A mutation. "Inheritance" is really a poor name - that should be used for what we now call "instantiation'.

    Because the child is the parent, the child has the same member data and methods that the parent does, unless the child overrides them. If the parent has a $this->foo element, the child does too.

    It feels to me like this is only partly true. Back to my original example (and the original question, forget settings files, it was just an example):

    What is the best way for a child class to access the _changed_ values of objects in it's parent?
    The same way the parent does.

    Let's put the question differently: Why do you think the child needs to access them?

    From where I sit, the child can be doing one of the following:

    • Implementing an interface specified but not elaborated by the parent.
    • Extending the parent by adding new functions.
    • Changing the behavior of the parent.
    • Removing behavior from the parent.

    The first and second cases don't care too much about the parent, obviously. The last case probably doesn't either. But when you're changing the behavior of the parent, you need to interfere somehow.

    Changing behavior is always a good time to investigate inserting what Marcus would call a "flex point" -- a method to handle some of the behavior.

    Regardless of whether there is a method specifically for the behavior or not, there are these choices for accessing data:

    • Tell the object (itself) to perform some computation and return the result.
    • Invoke an "accessor" that returns the value.
    • Directly access the member value.

    Unlike some, I hate "accessors", so I'm just not going to talk about them.

    Invoking a method to compute something is pretty straightforward, but eventually you need to write the "compute something". Before you do, you should consider how much access you need, and to what.

    Accessing a member value directly is just as easy as pie, and it doesn't matter if it is an inherited member or not. You just access it: $this->foo

    So to wrap it up:

    PHP Code:
     class Parent
     
    {
       var 
    $par_member;
     
       function 
    Parent($delim "'")
       {
         
    $this->par_member $delim;
       }
     
       function 
    delimit_string($str)
       {
         return 
    $this->par_member $str $this->par_member;
       }
     }
     
     class 
    Child
       
    extends Parent
     
    {
       function 
    Child($delim)
       {
         
    parent::Parent($delim);
       }
     
       function 
    emit_string($str)
       {
         
    # Invoking an inherited method.
         
    $output $this->delimit_string($str);
     
         
    # Accessing an inherited member
         
    $prefix = <<<END
     The delimiter is ${this->par_member}.
     
     The delimited string is: 
     END;
         echo 
    $prefix . $output . "\n";
       }
     } 
    =Austin

  9. #9
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You may want to read this article...

    Relying on inheritance for type identity is dangerous; it locks you into a particular inheritance hierarchy.
    Taken from Abstract Classes Vs Interfaces

    http://www.javaworld.com/javaqa/2001...bstract_p.html


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
  •