(Please no jokes about children!)
I constantly hear about inheritance being a prime factor in determining if something is OO or not, and how useful it is for OO programming. Everybook I read that talks about OO eventually mentions inheritance, along with the standard animal or car examples. But I don't think I've ever used inheriting in my life, not that my life is especially long or I've done lots of programming, but I've done a bit and I just never seem to use it.

So my question is, when/what have you actually used inheritance (for) in a 'real' project? Real in this case meaning a project not done solely for experimentation purposes.

Replies are listed 'Best First'.
Re: Real live usage of inheritance?
by Ovid (Cardinal) on Nov 05, 2003 at 18:07 UTC

    Take a look at HTML::TokeParser::Simple. That module inherits from HTML::TokeParser. It obeys the Liskov Substitution Principle, it truly extends the functionality and, I think, is a decent example of what inheritance can do (though it would be better if blessing the tokens had been pushed down to the parent classes).

    One problem with inheritence is determining what should really be inherited. For example, I see a lot of inheritence with no purpose other than to alter the object's data (that should probably be an instance) rather than altering (or extending) the object's behavior.

    Also, just because you can inherit from something doesn't mean you should. For example. one time I was creating a set of Web tests and inherited from WWW::Mechanize. Instead of an is-a relationship, I actually had a has-a relationship and I needed to rewrite my code to delegate method calls to a Mechanize object. While this was a good thing to do from a design standpoint, it was doubly important in Perl as it's so easy to accidentally step on the "private" methods of a class:

    package Foo; sub new { my $self = bless {}, shift; $self->_init } sub _init { 'initialize data here' } package Bar; use base 'Foo'; sub _init { warn "We didn't initialize our data :(\n" } package main; my $thing = Bar->new;

    Cheers,
    Ovid

    New address of my CGI Course.

      it was doubly important in Perl as it's so easy to accidentally step on the "private" methods of a class:

      In the case you present, I would argue that if the base methods are truly private, they should have been implemented as lexically scoped closures (declare my $init = sub { }; at the top of the package), not as a regular subroutine.

      It'd be nice if we could do away with the _subroutine_name idiom all together, but Perl doesn't currently provide a way to do protected methods (except by doing some fooling around with caller and isa, and even then it's only a runtime error), so the leading-underscore trick is the next best option.

      Since we have a trick for doing truly private functions (with closures), I consider any class that implements private method with a leading underscore to be broken. If it's a protected method, it should be documented for the benifit of subclasses (away from the public interface documentation, please).

      ----
      I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
      -- Schemer

      : () { :|:& };:

      Note: All code is untested, unless otherwise stated

        I would argue that if the base methods are truly private, they should have been implemented as lexically scoped closures (declare my $init = sub { }; at the top of the package), not as a regular subroutine.

        (Niggle: Making a subroutine lexically scoped doesn't mean it is a closure.)

        Since most of the time all you want with a private method is to prevent subclasses breaking because they override it, there are a couple of other ways of protecting yourself without using anonymous subroutines.

        package Foo; sub _my_private_method { ... }; # we can just call it as a subroutine, then no matter # what methods the subclass define we're okay. sub my_public_method1 { my $self = shift; ... _my_private_method($self); ... }; # We can also root the method call in the current # class sub my_public_method2 { my $self = shift; ... $self->Foo::_my_private_method; ... };
        It'd be nice if we could do away with the _subroutine_name idiom all together, but Perl doesn't currently provide a way to do protected methods (except by doing some fooling around with caller and isa, and even then it's only a runtime error), so the leading-underscore trick is the next best option.

        I've never come across people using the _method_name convention to indicate protected methods. Since most people use it to indicate private/implementation subroutines I'd probably consider it bad style myself.

        However, since I tend to find protected methods to be a bit of a code smell anyway I don't really care :-)

Re: Real live usage of inheritance?
by broquaint (Abbot) on Nov 05, 2003 at 18:02 UTC
    So my question is, when/what have you actually used inheritance (for) in a 'real' project?
    Indeed, many times. I've used it to determine standard data access behaviour across classes, to inherit from a base object defintion and generally adding structure to classes (e.g fielding out utility methods to a utility module so as to not clutter up the basic class definition). Perhaps the most obvious use is laziness - why bother maintaining X methods across Y classes, when you can just have your subclasses inherit from your main class and maintain the non-overriden methods there (and as you can probably guess, laziness isn't the only benefit).
    HTH

    _________
    broquaint

      Perhaps the most obvious use is laziness - why bother maintaining X methods across Y classes, when you can just have your subclasses inherit from your main class and maintain the non-overriden methods there . . .

      Eek! Such is really false-laziness, as it tends to break object relationships into whatever the programmer felt like at the time, instad of a logical flow. It tends to make things a lot harder over time, since two classes that really have nothing to do with each other are suddenly in a parent-child relationship, just because there was a bit of code in the parent that was also needed in the child.

      Down that path lies many a broken OO project.

      ----
      I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
      -- Schemer

      : () { :|:& };:

      Note: All code is untested, unless otherwise stated

        Eek! Such is really false-laziness ... since two classes that really have nothing to do with each other are suddenly in a parent-child relationship
        Er ... perhaps. But I meant to imply without inheritence, it's rather more difficult to maintain related modules, not to inherit just because of a common method. So in conclusion, inheritence is powerful, but has its dangers, like most useful programming constructs.
        HTH

        _________
        broquaint

Re: Real live usage of inheritance?
by Abigail-II (Bishop) on Nov 05, 2003 at 17:51 UTC
    The Perl internal datastructures for scalar values can be seen as an inheritance tree. Even while it's written in C. Or preprocessor macros. (Look ma! I can write OO in any language).

    Abigail

Re: Real live usage of inheritance?
by gjb (Vicar) on Nov 05, 2003 at 18:08 UTC

    I use inheritance quite a lot in real projects. One particular example in the old days was a framework for serialization/deserialization of objects in XML. This was implemented in both Perl and Java so that Perl objects could be serialized and deserialized as Java objects and vice versa. In both Perl and Java classes that implement this were subclasses of the 'GObject' class that had all the necessary logic.

    Another example: a library for finite state machines that also implements a finite state transducer. The latter adds functionality to the former, so it inherits all from the finite state automaton, but adds code to actually output things rather than just accepting or rejecting.

    Another example was a Perl wrapper around a C library that implemented connectivity to custom servers. All servers shared some functionality, but differed in the kind of requests one could do and the data they returned. Hence I had a base class implementing basic connectivity while the classes that inherited from it implemented the specific functionality.

    Oh well, very useful concept... just my 2 cents, -gjb-

Re: Real live usage of inheritance?
by hardburn (Abbot) on Nov 05, 2003 at 18:55 UTC

    Class::DBI and CGI::Application make heavy use of inheritance, as does Exporter, though I wouldn't really call that OO--it's more like using Perl's OO-ish features in a non-OO way.

    Right now, I'm in the middle of a project that needs to generate reports based on certain data. The reports could come out in HTML, PDF, Excel, or even a CSV for exporting to another system. I've worked this by having an ExportFormat class which specific report formats inheirt from. After the constructor is called, a record() method is called many times with the argument as a single row from the database (actually, a Class::DBI subclass containing a single row). When the application is done filling the data, it calls a done() method, which returns a filehandle that contains the completed report. Since this is a web application, each report also has a mime_type() method that gives the MIME type that should be sent back to the client for this report.

    I find this solution to be quite elegant.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      In this circumstances I tend to take a different approach - I would do the object creator taking as a parameter the done() function. I gues I am used to use higher order constructs.
Re: Real live usage of inheritance?
by tsee (Curate) on Nov 05, 2003 at 21:05 UTC
    I've been using inheritance in several CPAN modules of mine:
    • Math::Symbolic uses inheritance for methods that are common for all kinds of node types (Operators, Variables, Constants).
    • Physics::Particles -> Physics::Springs -> Physics::Springs::Friction use inheritance. Physics::Springs extends the particle simulations of Physics::Particles with spring-like forces (that is, exclusively acting between two particles), Physics::Springs::Friction adds friction to the simulation.
    • Math::Approx::Symbolic subclasses Math::Approx and adds a method that generates a Math::Symbolic tree from the polynomial approximation made by Math::Approx. (That can be used for computation directly, compilation to Perl subroutines, LaTeX dumps, etc.)

    Hope that's enough examples of inheritance in "real" projects.

    Steffen
Re: Real live usage of inheritance?
by perrin (Chancellor) on Nov 05, 2003 at 18:09 UTC
Re: Real live usage of inheritance?
by tilly (Archbishop) on Nov 05, 2003 at 19:47 UTC
    I have used inheritance more than I care to describe. It tends to be overused. But when it is the right tool to reach for, it is invaluable.

    If you want a real-world, understandable example using inheritance to mull over, grab libwww (that is LWP and friends) and study how that code works.

Re: Real live usage of inheritance?
by castaway (Parson) on Nov 05, 2003 at 22:14 UTC
    My .02 (euro)cents..

    I created a telnet client in perl, to which modules (plugins) can be added. The basic plugin has default values/methods for everything, each of the actual plugins inherits from this, and implements only the bits it actually needs. (Eg: The Alias module only implements the hooks to the user input methods, whereas the Trigger module needs the server input only). (Hmm, this'll probably only make sense to anyone who has played MUD or similar, whatever, you get the idea :)

    C.

Re: Real live usage of inheritance?
by Anonymous Monk on Nov 05, 2003 at 22:27 UTC

    Another good example of inheritance used in "real life" is the Bioperl open source project. There is, for instance, a Bio::Seq object, which encodes a general sequence. A variety of other types of sequence inherit off this general one.

    That project also makes use of a lot of interface and factory classes (which I've never really understood well, so anyone who can explain will earn my ever-lasting gratitude). For example, a current discussion in the project is the development of wrapper code for the BLAST series of software programs. One idea is to generate a BLASTI (I = interface) class, along with accessory codes for all the others. In that way, anyone using a BLAST tool has a core standard interface to use & learn.

Re: Real live usage of inheritance?
by pjf (Curate) on Nov 06, 2003 at 10:12 UTC
    Inheritance is often explained in terms of cars and animals because those learning it are often familiar with such concepts. However my life as a programmer would be much more difficult if it weren't for the powers that inheritance provides. I have too many cases to list here, but some examples that immediately spring to mind:

    • Users - Many systems have different types of users. Staff, clients, admins, auditors, and so on. Very often these all have a common set of methods and properties, and some are even sub-classes of each other (eg, admins are a special type of staff). This is one area that keeps coming up again and again.
    • CPAN modules - CPAN is great, but what happens when you find a module that does almost what you want, but not quite? You want it to do just a little bit more, or something a little bit differently? This is an excellent opportunity for inheritance. Without having to change the exist code you can add new features and functionality to your favourite CPAN modules.
    • The Finance::Quote::Yahoo::* modules all inherit from a common base. Yahoo provides excellent market information, but it varies from exchange to exchange. By inheriting from a common base, much time and effort is saved.
    • Portlets - I've worked for a number of portal businesses over my career, and guess what? Each 'portlet' or property inherits from a common class.
    • Much much more - CPAN provides a wealth of examples for using inheritance. Like any tool, the more you use it, the more familiar you become with its best applications.
Re: Real live usage of inheritance?
by adrianh (Chancellor) on Nov 06, 2003 at 11:04 UTC
    I constantly hear about inheritance being a prime factor in determining if something is OO or not, and how useful it is for OO programming.

    To some extent, inheritance is overemphasised by some people when talking about OO development. Not that it's completely useless, but you often find it used where options like delegation would be a better design choice.

    So my question is, when/what have you actually used inheritance (for) in a 'real' project? Real in this case meaning a project not done solely for experimentation purposes

    Some of my recent (real world) uses of inheritance have included:

    • Subclassing various CGI::Kwiki modules to provide some specialised formatting and behaviour.
    • Creating a memory-caching subclass of an object-relational persistance class.
    • Refactoring some common behaviour from several Test::Class classes into a common super-class.

    Basically, places where you want to specialise behaviour.

Re: Real live usage of inheritance?
by etcshadow (Priest) on Nov 06, 2003 at 19:44 UTC
    Well, I work on a large healthcare administration system, and we use inheritance a fair bit (both "real" inheritance via @ISA or use base as well as "fake" inheritance that is done manually, or via code attached to hierarchical data-structures of some form or another). A typical example is something like (BCBS is lingo for "Blue Cross and Blue Shield" and MA is Massachussets):

    "A BCBS-MA HMO Blue claim ISA BCBS-MA claim ISA BCBS claim ISA claim."

    Details get complicated and uninteresting from there, and that isn't quite an *exactly* correct example, but it gets the idea accross.

    There are business rules that apply specifically to BCBS-MA HMO Blue that make it behave differently than, say, BCBS-MA PPO. There are business rules that apply to all BCBS-MA plans that aren't common to other state/region BCBS's. There's also general stuff that all BCBS's have in common, but which are different when compared to large comercial insurance carriers like Aetna and Cigna, and likewise different from government carriers like Medicare, Medicaid and Champus (veterans). However, there are some things that are really the same between all of these.


    ------------
    :Wq
    Not an editor command: Wq
Re: Real live usage of inheritance?
by submersible_toaster (Chaplain) on Nov 10, 2003 at 08:30 UTC

    like in the wild? :)
    The cars and animal routine never really helped me much either. I have observed inheritance in the wild, a media class inherited by specific mediaaccessors (nfs,ftp,smb,stonefs) - viola ~ an agent calling methods of media class cares not about it's genesis.

    Abstract rate counters, have been spotted nesting with children who delight in measuring and playing with a variety of data such as;

    • Time (x)MB over 100TX
    • Frames (h) (m) (s) (f) NTSC
    • Time (x)GB DLT write
    • GigaBytes (h)(m)(s) PAL @ 720x576x24

    The children are shallow creatures , exhibiting a megre ammount of self.

    package Counter::FramesHMSFNTSC; @ISA( Counter ); init( hours=>[], minutes=>[ hours=>60 ], seconds=>[ minutes=>60 ], frames=>[ seconds=>30], atomic=>'frames', );
    Pretty gross perhaps, but very lazy since these are usually constant things.


    I can't believe it's not psellchecked