Is adding public methods to base classes bad design?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andrew Ward

    Is adding public methods to base classes bad design?

    Hi All,
    Sorry if this is off topic, but I could not seem to find a suitable OO
    Design newsgroup. If there is one feel free to let me know.

    Here is a simplification of a general design problem I face.

    Say you have:

    class Car {
    virtual void speedup();
    virtual void slowdown();
    };

    class BondCar {
    virtual void self_destruct() ;
    };

    Now storing a std::list<Car *> and calling speedup/slowdown is fine, however
    if you wanted to self_destruct all BondCars in the list I can think of a few
    ways to do it:

    1) Use dynamic_cast, this is obviously not a good solution for more complex
    designs.
    2) Bring self_destruct down into the base class, making a 'fat' interface
    3) Storing two lists, one std::list<Car *> and the other std::list<BondC ar
    *>, but then if I want to speed up all cars I have to iterate over two lists

    None of these solutions seems very well suited to more complex designs, and
    I have come across this problem over and over again. As it says in the c++
    faq lite, inheritance is for old code to call new code, and NOT for code
    reuse, so it almost seems to me that adding new public methods to derived
    classes is wrong.

    Could someone please enlighten me?
    Andy


  • David White

    #2
    Re: Is adding public methods to base classes bad design?


    Andrew Ward <anwar@ihug.co. nz> wrote in message
    news:EPe1b.1233 16$JA5.2851501@ news.xtra.co.nz ...[color=blue]
    > Hi All,
    > Sorry if this is off topic, but I could not seem to find a suitable OO
    > Design newsgroup. If there is one feel free to let me know.[/color]

    comp.object
    [color=blue]
    > Here is a simplification of a general design problem I face.
    >
    > Say you have:
    >
    > class Car {
    > virtual void speedup();
    > virtual void slowdown();
    > };
    >
    > class BondCar {
    > virtual void self_destruct() ;
    > };
    >
    > Now storing a std::list<Car *> and calling speedup/slowdown is fine,[/color]

    No it isn't. Those members are private.
    [color=blue]
    > however
    > if you wanted to self_destruct all BondCars in the list I can think of a[/color]
    few[color=blue]
    > ways to do it:
    >
    > 1) Use dynamic_cast, this is obviously not a good solution for more[/color]
    complex[color=blue]
    > designs.[/color]

    I always wince at having any dynamic_cast, but it's still the best of a bad
    choice of solutions in some cases.
    [color=blue]
    > 2) Bring self_destruct down into the base class, making a 'fat' interface[/color]

    If 'self_destruct' makes sense for all Cars, then it should be in Car. If it
    only makes sense for BondCars, then it should only be in BondCar. I don't
    think its location should be dictated by your application without regard for
    its proper place. I don't have a problem with "fat" interfaces. In fact, the
    more abstract the class in which you can put a member, the better, as long
    as the member makes sense in that class.
    [color=blue]
    > 3) Storing two lists, one std::list<Car *> and the other std::list<BondC ar
    > *>, but then if I want to speed up all cars I have to iterate over two[/color]
    lists

    A variation on 3) is to have one list with all Cars, including BondCars, and
    another with just BondCars. It's harder to delete a BondCar, as it has to be
    removed from both lists, but you don't need any downcasts and you don't need
    to put members in the wrong class.

    It's impossible to choose without knowing your application better.
    [color=blue]
    > None of these solutions seems very well suited to more complex designs,[/color]
    and[color=blue]
    > I have come across this problem over and over again. As it says in the c++
    > faq lite, inheritance is for old code to call new code, and NOT for code
    > reuse, so it almost seems to me that adding new public methods to derived
    > classes is wrong.[/color]

    I thought it was to represent IS-A relationships, but maybe I'm behind the
    times.

    There's nothing wrong with adding anything to anything as long as it solves
    your problem, makes sense, and doesn't cause a maintenance nightmare.
    [color=blue]
    > Could someone please enlighten me?[/color]

    That's about the best I can do.

    DW



    Comment

    • jeffc

      #3
      Re: Is adding public methods to base classes bad design?


      "Andrew Ward" <anwar@ihug.co. nz> wrote in message
      news:EPe1b.1233 16$JA5.2851501@ news.xtra.co.nz ...[color=blue]
      > Hi All,
      > Sorry if this is off topic, but I could not seem to find a suitable OO
      > Design newsgroup. If there is one feel free to let me know.
      >
      > Here is a simplification of a general design problem I face.
      >
      > Say you have:
      >
      > class Car {
      > virtual void speedup();
      > virtual void slowdown();
      > };
      >
      > class BondCar {
      > virtual void self_destruct() ;
      > };[/color]

      I'm assuming those are supposed to be public functions.
      [color=blue]
      > Now storing a std::list<Car *> and calling speedup/slowdown is fine,[/color]
      however[color=blue]
      > if you wanted to self_destruct all BondCars in the list I can think of a[/color]
      few[color=blue]
      > ways to do it:[/color]

      First, I think you should take a step back and ask yourself about the
      implications of a design where you would even consider having a list of base
      class objects, and then attempting to do subclass functions on only some of
      those objects. This isn't a trivial subject.
      [color=blue]
      > None of these solutions seems very well suited to more complex designs,[/color]
      and[color=blue]
      > I have come across this problem over and over again. As it says in the c++
      > faq lite, inheritance is for old code to call new code, and NOT for code
      > reuse, so it almost seems to me that adding new public methods to derived
      > classes is wrong.[/color]

      Generally speaking, I can't imagine why public methods in subclasses could
      be wrong. Inheritance is used often, even when there is no such thing as
      "old" code and "new" code. i.e. it's used right in the original design.
      Anyway, I don't think you have a fundamental OO problem with inheritance, I
      think you have a specific design issue related to lists of things. You can
      do more reading in this area. The C++ FAQs book by Cline is a short start
      (is bag-of-apple a kind-of bag-of-fruit?, etc.)


      Comment

      • ES Kim

        #4
        Re: Is adding public methods to base classes bad design?

        "Andrew Ward" <anwar@ihug.co. nz> wrote in message
        news:EPe1b.1233 16$JA5.2851501@ news.xtra.co.nz ...[color=blue]
        > Hi All,
        > Sorry if this is off topic, but I could not seem to find a suitable OO
        > Design newsgroup. If there is one feel free to let me know.
        >
        > Here is a simplification of a general design problem I face.
        >
        > Say you have:
        >
        > class Car {
        > virtual void speedup();
        > virtual void slowdown();
        > };
        >
        > class BondCar {
        > virtual void self_destruct() ;
        > };
        >
        > Now storing a std::list<Car *> and calling speedup/slowdown is fine, however
        > if you wanted to self_destruct all BondCars in the list I can think of a few
        > ways to do it:
        >
        > 1) Use dynamic_cast, this is obviously not a good solution for more complex
        > designs.
        > 2) Bring self_destruct down into the base class, making a 'fat' interface
        > 3) Storing two lists, one std::list<Car *> and the other std::list<BondC ar
        > *>, but then if I want to speed up all cars I have to iterate over two lists
        >
        > None of these solutions seems very well suited to more complex designs, and
        > I have come across this problem over and over again. As it says in the c++
        > faq lite, inheritance is for old code to call new code, and NOT for code
        > reuse, so it almost seems to me that adding new public methods to derived
        > classes is wrong.
        >
        > Could someone please enlighten me?
        > Andy[/color]

        I've encountered a similar situation where self_destruct() makes sense only
        for BondCar. I'm considering introduction of a member which tells me to what
        class a specific object belongs. Then I can check the member before applying
        self_destruct() to an object. It's not the OO way, my code would look ugly,
        but I expect it'll work. Any suggestion please?

        --
        ES Kim


        Comment

        • John Harrison

          #5
          Re: Is adding public methods to base classes bad design?


          "ES Kim" <eskim@svd.co.k r> wrote in message
          news:bi66ga$1ju $1@news1.kornet .net...[color=blue]
          > "Andrew Ward" <anwar@ihug.co. nz> wrote in message
          > news:EPe1b.1233 16$JA5.2851501@ news.xtra.co.nz ...[color=green]
          > > Hi All,
          > > Sorry if this is off topic, but I could not seem to find a suitable OO
          > > Design newsgroup. If there is one feel free to let me know.
          > >
          > > Here is a simplification of a general design problem I face.
          > >
          > > Say you have:
          > >
          > > class Car {
          > > virtual void speedup();
          > > virtual void slowdown();
          > > };
          > >
          > > class BondCar {
          > > virtual void self_destruct() ;
          > > };
          > >
          > > Now storing a std::list<Car *> and calling speedup/slowdown is fine,[/color][/color]
          however[color=blue][color=green]
          > > if you wanted to self_destruct all BondCars in the list I can think of a[/color][/color]
          few[color=blue][color=green]
          > > ways to do it:
          > >
          > > 1) Use dynamic_cast, this is obviously not a good solution for more[/color][/color]
          complex[color=blue][color=green]
          > > designs.
          > > 2) Bring self_destruct down into the base class, making a 'fat'[/color][/color]
          interface[color=blue][color=green]
          > > 3) Storing two lists, one std::list<Car *> and the other[/color][/color]
          std::list<BondC ar[color=blue][color=green]
          > > *>, but then if I want to speed up all cars I have to iterate over two[/color][/color]
          lists[color=blue][color=green]
          > >
          > > None of these solutions seems very well suited to more complex designs,[/color][/color]
          and[color=blue][color=green]
          > > I have come across this problem over and over again. As it says in the[/color][/color]
          c++[color=blue][color=green]
          > > faq lite, inheritance is for old code to call new code, and NOT for code
          > > reuse, so it almost seems to me that adding new public methods to[/color][/color]
          derived[color=blue][color=green]
          > > classes is wrong.
          > >
          > > Could someone please enlighten me?
          > > Andy[/color]
          >
          > I've encountered a similar situation where self_destruct() makes sense[/color]
          only[color=blue]
          > for BondCar. I'm considering introduction of a member which tells me to[/color]
          what[color=blue]
          > class a specific object belongs. Then I can check the member before[/color]
          applying[color=blue]
          > self_destruct() to an object. It's not the OO way, my code would look[/color]
          ugly,[color=blue]
          > but I expect it'll work. Any suggestion please?
          >[/color]

          It would be better to use dynamic_cast.

          john


          Comment

          • David White

            #6
            Re: Is adding public methods to base classes bad design?

            "ak" <ak @ workmail.com> wrote in message
            news:ra9fkvkvat bjnon3rc2jodfbd df1sahccq@4ax.c om...[color=blue]
            > On Fri, 22 Aug 2003 14:01:13 +1200, "Andrew Ward" <anwar@ihug.co. nz>[/color]
            wrote:[color=blue]
            >
            > |1) Use dynamic_cast, this is obviously not a good solution for more[/color]
            complex[color=blue]
            > |designs.
            > |2) Bring self_destruct down into the base class, making a 'fat' interface
            > |3) Storing two lists, one std::list<Car *> and the other[/color]
            std::list<BondC ar[color=blue]
            > |*>, but then if I want to speed up all cars I have to iterate over two[/color]
            lists[color=blue]
            > |
            > |None of these solutions seems very well suited to more complex designs,[/color]
            and[color=blue]
            > |I have come across this problem over and over again. As it says in the[/color]
            c++[color=blue]
            > |faq lite, inheritance is for old code to call new code, and NOT for code
            > |reuse, so it almost seems to me that adding new public methods to derived
            > |classes is wrong.
            >
            >
            > I would go for (2), having a virtual self_destruct() in base class which[/color]
            does[color=blue]
            > nothing but implemented in the derived class.[/color]

            So where you have:
            pCar->self_destruct( );

            the car will refuse unless it's a BondCar? A self-destruct that leaves the
            car intact.

            DW



            Comment

            Working...