SitePoint Sponsor

User Tag List

Results 1 to 22 of 22
  1. #1
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    When to use inheritance?

    I know we've all heard the phrase, "favor composition over inheritance"... and I try as much as I can to do that in my code. I'm wondering, though, when it makes sense to use inheritance over composition? Is there some rule to judge when something is a better fit for one over the other?

  2. #2
    Coding and Breathing CoderMaya's Avatar
    Join Date
    Feb 2008
    Location
    Atlit, Israel
    Posts
    470
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Whenever you see yourself reusing bits of code in different classes, or when some classes just require those bits of codes because they are pretty much meant to be extended versions of other classes, such as Person, Employee and Project Manager, which could all have a name (inherited from Person), salary (inherited from Employee which inherits the name from Person) and so forth.

    Hope you got it. If not let me know and I'll try to explain further.
    Last edited by CoderMaya; Aug 31, 2008 at 02:35.
    Learn about the new Retro Framework
    Code PHP the way it was meant to be coded!

  3. #3
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by allspiritseve View Post
    I know we've all heard the phrase, "favor composition over inheritance"... and I try as much as I can to do that in my code. I'm wondering, though, when it makes sense to use inheritance over composition? Is there some rule to judge when something is a better fit for one over the other?
    Object oriented theory has it that you should distinguish between is-a and has-a, to chose between inheritance and composition, but in practice this model soon breaks down. The problem is that the distinction isn't as black-and-white as it's made out to be; Real things get their meaning from a context, so when the context changes, they may change their meaning. Inheritance - being a static relationship - doesn't support this.

    I'd say that it's a pragmatic choice. There are situations where it's just way more practical to use inheritance. Generally speaking though, it's mostly a hack. So from a purist point of view, I'll say that it's never better to use inheritance. In practice, well, some times you have to.

  4. #4
    Coding and Breathing CoderMaya's Avatar
    Join Date
    Feb 2008
    Location
    Atlit, Israel
    Posts
    470
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't know. I'll tell you one good thing about inheritance. When you don't know exactly what type of object you have stored in a variable, but you do know that it extends from Person so it must have at least a property named name, for example, then you can go over an entire database of people in different ranks and titles easily, because they'll all contain that name, since they extend person.

    foreach($people as $person) echo $person->name;

    Doesn't matter if it's a Person object, Employee object, ProjectManager or anything else that somewhere extends down to Person.
    Learn about the new Retro Framework
    Code PHP the way it was meant to be coded!

  5. #5
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by CoderMaya View Post
    I don't know. I'll tell you one good thing about inheritance. When you don't know exactly what type of object you have stored in a variable, but you do know that it extends from Person so it must have at least a property named name, for example (...)
    Class inheritance is a mix of two concepts. The extending class inherits the parents implementation (functions/methods) and it inherits the parents type. In a statically typed language, the latter is fairly important, since you can't freely mix types. So if some method expects an argument of a given type, you might use inheritance to satisfy this. In a dynamically typed language that is a non-issue. You can simply implement the expected behaviour and that's all there is to it. If you need a more explicit contract, you can document it or - since PHP has sort of a middle-way on this matter - you could use a statically typed interface (Eg. implements Person, rather than extends Person) to do the same thing. Since PHP is dynamically typed, this (slightly more verbose and restrictive) solution is purely optional. You can just use an implicit contract (duck typing).

    The other use of class inheritance is to reuse implementation. If your abstract class Person is extended by a subclass Employer, you would have access to the same code in Employer as you do in Person. You could achieve code-reuse with composition as well, but it takes a bit more work. Employer would have to implement a wrapper that delegates control to a Person instance in this case. Eg.:
    PHP Code:
    class Person {
      function 
    sayHello() {
        echo 
    "Hello, World!";
      }
    }
    class 
    Employer {
      protected 
    $person;
      function 
    __construct() {
        
    $this->person = new Person();
      }
      function 
    sayHello() {
        
    $this->person->sayHello();
      }

    rather than:
    PHP Code:
    class Person {
      function 
    sayHello() {
        echo 
    "Hello, World!";
      }
    }
    class 
    Employer extends Person {} 
    As you can see, slightly more work to do, which is why people often use inheritance in these cases. The cost however, is that the Person-Employer relationship is now set in stone; It can't be changed or intercepted at runtime. There is also the matter of clarity. While the compositional code is more verbose, it is also very clear about what it does. You can look at the code and know what it does. With the inheritance version, you need to look at the superclass to find out what it does. Some times there are multiple levels of inheritance, making you trace up and down the chain to figure out exactly what code is available in the concrete class. Finally, there is the problem of multiple inheritance. In PHP, you can't. You only have one shot at inheritance, so if you want to reuse code from two places, well, you're out of luck.

  6. #6
    Coding and Breathing CoderMaya's Avatar
    Join Date
    Feb 2008
    Location
    Atlit, Israel
    Posts
    470
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    For multiple level inheritance I use editors with code-insight.

    By the way I personally never got stuck in a position where I wanted multiple inheritance. I find that avoiding it results in more organized, maintainable code.

    And a perfect example for proper use of inheritance is the MVC structure, wouldn't you say? Creating a complex multi functional section is as easy as creating a class that extends from Controller.
    Learn about the new Retro Framework
    Code PHP the way it was meant to be coded!

  7. #7
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    A good use of inheritance I take advantage of is when you have a function you want to use in many classes, but want to make it quickly changable too.

    An example is if you have a class with functions and properties you require in others:
    PHP Code:
    <?php
    class BaseObject{
        protected 
    $id//all objects may have an ID attatched to them
        
    function __Call($method$params){ //allows you to get/set a public/protected using getVarName() - e.g. for $obj->bob it would be $obj->getBob() and $obj->setBob(...);
            
    $action substr($method03);
            
    $what substr($method3);
            if(isset(
    $this->$what)){
                
    $Obj =& $this->$what;
                switch(
    $action){
                    case 
    'get':
                        return 
    $Obj;
                    break;
                    case 
    'set':
                        if(
    count($params) > 0){
                            return 
    $Obj $params[0];
                        }else{
                            return 
    false;
                        }
                    break;
                }
            }else{
                return 
    false;
            }
            return 
    false;
        }
    }
    Any class can now extend that and have the same functionality.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  8. #8
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by CoderMaya View Post
    For multiple level inheritance I use editors with code-insight.
    Yes, IDE's are good at that stuff. There are even better at it, if the language is statically typed. You could also turn that argument around and say that any language construct, that needs an IDE to keep you sane, is fundamentally flawed. But that's a matter of opinion.

    Quote Originally Posted by CoderMaya View Post
    By the way I personally never got stuck in a position where I wanted multiple inheritance.
    I find that hard to believe. If you use inheritance as a vessel for code-reuse, then you will run into trouble, if your code isn't all stuffed into one single, giant GodClass.

    Quote Originally Posted by CoderMaya View Post
    And a perfect example for proper use of inheritance is the MVC structure, wouldn't you say? Creating a complex multi functional section is as easy as creating a class that extends from Controller.
    Well, no. That's an example of good appliance of code-reuse. But you don't need to use inheritance to get code-reuse.

    Quote Originally Posted by arkinstall View Post
    A good use of inheritance I take advantage of is when you have a function you want to use in many classes, but want to make it quickly changable too.
    Again, this is code-reuse. You could do the same with delegation, even if it would have a slight bit of verbosity/redundancy. PHP doesn't support multiple inheritance, so creating base-classes like that, is a very bad idea. You either have to stuff all sorts of unrelated code into the same base-class, or you need to use delegation anyway and could as well have done so from the outset.

  9. #9
    Coding and Breathing CoderMaya's Avatar
    Join Date
    Feb 2008
    Location
    Atlit, Israel
    Posts
    470
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Can't say I agree with you. I guess it's a matter of opinion.

    The .NET framework developers decided not to include multiple inheritance, and look, they have arguably the biggest most robust framework in the world. And everything is object-oriented.
    Learn about the new Retro Framework
    Code PHP the way it was meant to be coded!

  10. #10
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arkinstall View Post
    A good use of inheritance I take advantage of is when you have a function you want to use in many classes, but want to make it quickly changable too.
    Inheritance is a card you can only play once, and by choosing to make a "BaseObject" you have played your special card on the first hand without thinking.

    Some other thoughts on the Inheritance vs. Composition debate: http://c2.com/cgi/wiki?CompositionInsteadOfInheritance
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  11. #11
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by CoderMaya View Post
    Can't say I agree with you. I guess it's a matter of opinion.

    The .NET framework developers decided not to include multiple inheritance, and look, they have arguably the biggest most robust framework in the world. And everything is object-oriented.
    I don't quite follow you? Maybe you misunderstood what I was trying to say? I didn't suggest that you should use multiple inheritance, because - well - you can't. PHP doesn't allow it. What I meant was that if you use inheritance for code-reuse, then you can only ever reuse one piece of code. That's a severe limitation.

  12. #12
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Inheritance is a card you can only play once, and by choosing to make a "BaseObject" you have played your special card on the first hand without thinking.
    You can play that card in the parent class and simply extend that.

    PHP Code:
    <?php
    Class base{
        function 
    sayHi(){
            return 
    'hi';
        }
    }
    Class 
    James extends base{
        function 
    __construct(){
            echo 
    $this->sayHi();
        }
    }
    Class 
    Bob extends James{
        function 
    __construct(){
            echo 
    $this->sayHi();
        }
    }
    new 
    Bob();
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  13. #13
    SitePoint Addict chestertondevelopment's Avatar
    Join Date
    Dec 2005
    Location
    Essex, UK
    Posts
    241
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think the point is; what if James needs to extend a different class, Database for example, but then another class, Timothy, also needs to extend Database but doesn't need the functionality of Base?

  14. #14
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arkinstall View Post
    You can play that card in the parent class and simply extend that.
    And what if the parent class shouldn't include said aspect? Say you have these two generic classes:
    PHP Code:
    class RegistryAccess {
      protected 
    $registry;
      function 
    __construct($registry) {
        
    $this->registry $registry;
      }
      function 
    __get($name) {
        return 
    $this->registry->get($name);
      }
    }
    class 
    Observable {
      protected 
    $listeners = array();
      function 
    connect($event$observer) {
        
    $this->listeners[$event][] = $observer;
      }
      function 
    signal($event) {
        foreach (
    $this->listeners[$event] as $observer) {
          
    $observer();
        }
      }

    The first is a somewhat simpler variant of the class you have used already as an example. The latter is a pretty common pattern, that often gets implemented in some form, so I've made a generic implementation. Now, let's assume that you may not always want both things in your classes. Some times you need registryaccess and some times you don't. And some times you need an observable and some times you don't. Now you're stuck. You can't have your class Foo extend from both these generic classes, and making one of them extend the other doesn't make sense either, because that would

  15. #15
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    That would....?

    I wouldn't see a problem with extending RegistryAccess to observable to extend functionality - but I do see what you mean.

    So what would be your solution to a situation like this?
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  16. #16
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje View Post
    Inheritance is a card you can only play once, and by choosing to make a "BaseObject" you have played your special card on the first hand without thinking.
    In your opinion, when would be the right time to play that "special card"?

  17. #17
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by allspiritseve View Post
    In your opinion, when would be the right time to play that "special card"?
    Sometime third party software allows only this option for integration. For example, you subclass the Zend_Controller_Action in order to add your own controller if you are using the Zend Framework. You subclass definitely "Is A" controller, so it satisfies the "is a" vs. "has a" question on the correct side.

    If you are in total control, go with the maxim "favor composition over inheritance".

    BTW, There are design patterns which specify the use of inheritance. The whole "Template method" pattern is just following good subclassing practices. However, you will probably end up with a more flexible solution if you use the Strategy pattern instead.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  18. #18
    SitePoint Enthusiast
    Join Date
    Jul 2008
    Posts
    53
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    BTW, There are design patterns which specify the use of inheritance. The whole "Template method" pattern is just following good subclassing practices. However, you will probably end up with a more flexible solution if you use the Strategy pattern instead.
    There is one special thing with subclassing, compared to the strategy pattern.

    With the strategy pattern you have a clear and fixed interface dictating what functionality depends on the strategy, and what functionality is fixed.

    With inheritance, you can let the subclass decide which functionality it should override.

    PHP Code:
    class Parent {
      function 
    f() {
        
    $this->ff();
      }
      protected function 
    ff() {
        
    $this->fff();
      }
      protected function 
    fff();
    }

    class 
    ChildA extends Parent {
      function 
    fff() {...}
    }

    class 
    ChildB extends Parent {
      function 
    ff() {...}
    }

    class 
    ChildC extends Parent {
      function 
    f() {...}


    If we want a strategy to be able to override f(), we have to add an explicit flex point in the parent class. With inheritance, this flex point comes (almost) for free.

    So, the guideline I would suggest:
    • If you already know that there will be different alternatives, or if your class grows too big, make an explicit flex point for strategy / composition.
    • If overriding a specific method is too unlikely, and your class is small enough, then consider inheritance.

    Hm, I hope that makes sense...

  19. #19
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    I'd say that it's a pragmatic choice. There are situations where it's just way more practical to use inheritance. Generally speaking though, it's mostly a hack. So from a purist point of view, I'll say that it's never better to use inheritance. In practice, well, some times you have to.
    Any chance you could explain your reasoning behind using inheritance for your controllers in konstrukt? Was that simply an ease-of-use thing for people wanting to quickly use your framework?

    I am looking at implementing a routing system that takes the place of your $map array and looks up subcontrollers in the database. (I want clients to be able to reorganize their content, so I'm keeping the "wire" that links all the controllers together in the db). I am attempting to implement this through composition so I can fully test each component, based on your handleRequest(), getNext(), forward(), etc. methods. It's proving to be a little tricky without inheritance, though.

  20. #20
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by allspiritseve View Post
    Any chance you could explain your reasoning behind using inheritance for your controllers in konstrukt? Was that simply an ease-of-use thing for people wanting to quickly use your framework?
    Tough question. There are at least two reasons. First off, it's a matter of convenience. Konstrukt is a library, that is intended to be used by other programmers, so there need to be a clear interface, while still allowing a lot of flexibility. While you can get this with composition, it's also quite explicit. Normally this is a good thing, but for someone starting out with a library, it's perhaps a bit much. Especially considering that you would seldom need to use these hooks. Using inheritance makes it a bit easier on newcomers, because they don't need to be aware of as many of the inner workings as otherwise. In retrospect though, I'm not sure how well founded this is. In part, it was probably a semi-conscious choice at best, where I simply picked the simplest solution.

    The other reason, is that a controller needs to both inherit implementation and interface (type), so that makes it a candidate for inheritance. In it self, this is probably not enough reason, but a controller is conceptually very tightly coupled to the framework. Even if the implementation decoupled it (Eg. through composition), it wouldn't really have any impact, because it doesn't make much sense to use a controller outside the context of the framework. So the implementation doesn't really take anything away in that sense. Arguably, this is a problem in it self, but I think it's inherently coupled with the whole concept of a framework in the first place. It is at least a recurring pattern, if you look at other similar frameworks. It would perhaps be interesting to try to break with this pattern. If you have been following the development of Konstrukt, then you'll see that that is exactly what happened to forms. In earlier versions, k_Form extended from k_Controller, but this has since changed so that today a k_Controller has a k_FormBehaviour.

  21. #21
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    Tough question.
    I tend to ask those a lot

    Quote Originally Posted by kyberfabrikken View Post
    there need to be a clear interface, while still allowing a lot of flexibility. While you can get this with composition, it's also quite explicit.
    I think this is the problem I'm coming across, trying to make a composition solution from your inheritance... each controller would have to explicitely call handleRequest(), forward(), and execute() just to function like one that inherited from a parent controller, whereas with konstrukt, the controllers could be as simple as a GET() method.

    Quote Originally Posted by kyberfabrikken View Post
    It is at least a recurring pattern, if you look at other similar frameworks. It would perhaps be interesting to try to break with this pattern.
    Very true, though I haven't seen a similar use of distributed routing like konstrukt... everyone seems to prefer central routing.

  22. #22
    Resident OCD goofball! bronze trophy Serenarules's Avatar
    Join Date
    Dec 2002
    Posts
    1,911
    Mentioned
    26 Post(s)
    Tagged
    0 Thread(s)
    To put in my two cents, along with everybody else's replies...

    In addition to everything mentioned above, a lot of it is just down to common sense. What are you trying to accomplish in a given instance? Is it to truly extend something? As in a Person class being extended into EmployeePerson and ClientPerson? Or it is to make subsequent same-level children easier to implement?

    As an example:

    When writing my own applications I tend to wrap a data record type in a model that does nothing but maintain a set of data. That's it. Validations are done by a seperate, dedicated class that acts on such a model. But I'll have many models laying around and don't want all that code duped. So I made an abstract base Model class. This class provides all the functionality that ALL my model-based classes will have.

    So...

    If you have two or more same-level classes that are based on a similar concept, by all means, abstract them to a base.

    If you have a categorical need (this is-a that, and that is-a other thing) then by all means use inheritance.


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
  •