Composition versus Implementation Inheritance

Discussion in 'C++' started by chsalvia@gmail.com, Jul 28, 2007.

  1. Guest

    Most modern sources on C++ design say that composition is usually
    preferable to implementation inheritance because inheritance tends to
    lead to problems down the road unless it follows a strict model
    allowing substitution, where each derived class has an "is-a"
    relationship with the base class.

    I was wondering, however, if implementation inheritance (private
    inheritance) might be a better idea in some cases. Consider the SGI C+
    + extension implementation of hash_set and hash_map. Both hash_set
    and hash_map use composition to reuse code from an internal class.
    They each have an internal hash_table class, which implements the
    basic functions of a hash table. The hash_set and hash_map class use
    delegation to access the functionality of the internal hash_table
    class. Google's sparse hash map/hash set also uses the same design
    scheme.

    This is a nice clean design, except one thing about it really bothers
    me. There's nothing preventing someone from instantiating an instance
    of the internal hash_table class somewhere else. Unlike an abstract
    base class, or a base class with a protected constructor, the internal
    hash_table "base" class can be instantiated anywhere, even though this
    would be useless.

    But if the hash_set and hash_map class used private inheritance to
    access the hash_table class, rather than composition/delegation, then
    the hash_table class could have been written with a protected
    constructor so that it couldn't be instantiated outside of a derived
    class.

    Plus, all the usual arguments against implementation inheritance
    wouldn't really apply, since the hash_set and hash_map classes are not
    designed to be inherited from anyway. (They have no virtual
    destructor, like all STL-ish classes.)

    Does anyone agree with me here? Or am I missing some more compelling
    reasons to stick with composition/delegation in this case?
     
    , Jul 28, 2007
    #1
    1. Advertising

  2. Daniel T. Guest

    wrote:

    > Most modern sources on C++ design say that composition is usually
    > preferable to implementation inheritance because inheritance tends to
    > lead to problems down the road unless it follows a strict model
    > allowing substitution, where each derived class has an "is-a"
    > relationship with the base class.
    >
    > I was wondering, however, if implementation inheritance (private
    > inheritance) might be a better idea in some cases. Consider the SGI C+
    > + extension implementation of hash_set and hash_map. Both hash_set
    > and hash_map use composition to reuse code from an internal class.
    > They each have an internal hash_table class, which implements the
    > basic functions of a hash table. The hash_set and hash_map class use
    > delegation to access the functionality of the internal hash_table
    > class. Google's sparse hash map/hash set also uses the same design
    > scheme.
    >
    > This is a nice clean design, except one thing about it really bothers
    > me. There's nothing preventing someone from instantiating an instance
    > of the internal hash_table class somewhere else. Unlike an abstract
    > base class, or a base class with a protected constructor, the internal
    > hash_table "base" class can be instantiated anywhere, even though this
    > would be useless.


    The question that immediately comes to mind here is: Why should this
    bother you? What's wrong with reusable code?

    > Does anyone agree with me here? Or am I missing some more compelling
    > reasons to stick with composition/delegation in this case?


    I'm not sure yet.
     
    Daniel T., Jul 28, 2007
    #2
    1. Advertising

  3. On 2007-07-28 08:21, wrote:
    > Most modern sources on C++ design say that composition is usually
    > preferable to implementation inheritance because inheritance tends to
    > lead to problems down the road unless it follows a strict model
    > allowing substitution, where each derived class has an "is-a"
    > relationship with the base class.
    >
    > I was wondering, however, if implementation inheritance (private
    > inheritance) might be a better idea in some cases. Consider the SGI C+
    > + extension implementation of hash_set and hash_map. Both hash_set
    > and hash_map use composition to reuse code from an internal class.
    > They each have an internal hash_table class, which implements the
    > basic functions of a hash table. The hash_set and hash_map class use
    > delegation to access the functionality of the internal hash_table
    > class. Google's sparse hash map/hash set also uses the same design
    > scheme.
    >
    > This is a nice clean design, except one thing about it really bothers
    > me. There's nothing preventing someone from instantiating an instance
    > of the internal hash_table class somewhere else. Unlike an abstract
    > base class, or a base class with a protected constructor, the internal
    > hash_table "base" class can be instantiated anywhere, even though this
    > would be useless.


    So what if they can be instantiated, what harm would it do. As you say
    it will probably be useless but you can't know the needs of every
    developer out there. I think this is kind of making it impossible to
    inherit from a class, I can't see any need for it. All it would
    accomplish would be to prevent possible ways of implementation.

    Since you can't anticipate all the requirements that might be placed on
    your application in the future you should try to not artificially limit
    the extensibility of your code (unless it makes it easier to satisfy the
    current requirement).

    --
    Erik Wikström
     
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=, Jul 28, 2007
    #3
  4. Guest

    I suppose I tend to think that, from a design point of view, if it
    doesn't make any sense to instantiate a certain class outside of
    another class, than this should be reflected somehow in the code, e.g.
    by having a protected constructor.

    It's true that you can never anticipate all the future requirements of
    developers down the road, but doing so would not really limit
    extensibility, because a future develop can always use private
    inheritance if they want to extend the class.
     
    , Jul 28, 2007
    #4
  5. Daniel T. Guest

    wrote:

    > I suppose I tend to think that, from a design point of view, if it
    > doesn't make any sense to instantiate a certain class outside of
    > another class, than this should be reflected somehow in the code, e.g.
    > by having a protected constructor.
    >
    > It's true that you can never anticipate all the future requirements of
    > developers down the road, but doing so would not really limit
    > extensibility, because a future develop can always use private
    > inheritance if they want to extend the class.


    Which defeats the purpose of making the constructor protected, so why
    bother?

    The fact is, we have a class that has already been used in two contexts,
    why assume that it wouldn't be useful in any others?

    On the other hand, we are talking about a class that is not documented
    and therefore cannot be expected to perform in any particular way so
    anyones use of that class outside of those two contexts is hazardous.

    You are asking here why use composition over private inheritance. How
    about we turn the question around, why use private inheritance over
    composition? Now that question has a solid answer, there are things that
    you can do with private inheritance that you simply can't do with
    composition, and if you need or want to do those things, then private
    inheritance is what you use.

    So now we can ask your original question again. If we are not using the
    features that private inheritance provides, then we are telling
    developers something about our class by no using private inheritance.
    Composition sends a message to anyone looking at the class, "don't
    bother worrying about me doing x, or y because that can't be done with a
    composition relationship.
     
    Daniel T., Jul 28, 2007
    #5
  6. Guest

    On Jul 28, 6:53 pm, "Daniel T." <> wrote:
    > Which defeats the purpose of making the constructor protected, so why
    > bother?
    >
    > The fact is, we have a class that has already been used in two contexts,
    > why assume that it wouldn't be useful in any others?


    The purpose of making the constructor protected would be to basically
    warn developers that this class should not be used on its own.
    However, if some developer wanted to create a different type of hash
    container some day, then that could be accomplished through private
    inheritance. This way, a developer would need to specifically have in
    mind the goal of extending the class in order to use the class. The
    possibility of simply declaring an instance of the class somewhere
    else would be eliminated.

    > On the other hand, we are talking about a class that is not documented
    > and therefore cannot be expected to perform in any particular way so
    > anyones use of that class outside of those two contexts is hazardous.
    >
    > You are asking here why use composition over private inheritance. How
    > about we turn the question around, why use private inheritance over
    > composition? Now that question has a solid answer, there are things that
    > you can do with private inheritance that you simply can't do with
    > composition, and if you need or want to do those things, then private
    > inheritance is what you use.
    >
    > So now we can ask your original question again. If we are not using the
    > features that private inheritance provides, then we are telling
    > developers something about our class by no using private inheritance.
    > Composition sends a message to anyone looking at the class, "don't
    > bother worrying about me doing x, or y because that can't be done with a
    > composition relationship.


    Basically, it seems you're saying that the possible danger of
    declaring a class outside of its appropriate context is not a
    sufficient reason by itself to use private inheritance. Perhaps
    you're right about that. Obviously, the SGI developers, who are much
    more experienced than I am, thought that composition was a better
    solution.

    I was just thinking that in a case where you have class A, B and C,
    where B and C use A internally, and declaring A anywhere else would be
    senseless or possibly dangerous, it would be beneficial to somehow
    restrict developers from instantiating A, *unless* they are
    specifically trying to extend A, in which case they're probably well
    aware of how A works. Otherwise, the only thing preventing someone
    from instantiating A anywhere would be a warning in the source or
    something.
     
    , Jul 29, 2007
    #6
  7. Daniel T. Guest

    wrote:
    > "Daniel T." <> wrote:


    > Basically, it seems you're saying that the possible danger of
    > declaring a class outside of its appropriate context is not a
    > sufficient reason by itself to use private inheritance.


    No, I'm saying that even if you do declare all class' constructors
    protected, the class can still be used outside of its appropriate
    context.

    > I was just thinking that in a case where you have class A, B and C,
    > where B and C use A internally, and declaring A anywhere else would
    > be senseless or possibly dangerous, it would be beneficial to
    > somehow restrict developers from instantiating A, *unless* they are
    > specifically trying to extend A, in which case they're probably well
    > aware of how A works.


    If a library vendor has developed A for internal use (i.e., they have
    not documented it,) it is "senseless or possibly dangerous" for anybody
    other than them to use it, *even* if they are specifically trying to
    extend it. Being "well aware of how A works" is irrelevant because the
    vendor can make major changes to the way A works between versions (it is
    not a published interface.)
    <http://www.martinfowler.com/ieeeSoftware/published.pdf>

    It would probably be nice to have some form of library level access
    privileges, however C++ doesn't have anything like that and I think
    abusing class level privileges in an attempt to simulate it is
    inappropriate.
     
    Daniel T., Jul 29, 2007
    #7
  8. James Kanze Guest

    On Jul 28, 3:39 pm, Erik Wikström <> wrote:
    > On 2007-07-28 08:21, wrote:
    > > Most modern sources on C++ design say that composition is usually
    > > preferable to implementation inheritance because inheritance tends to
    > > lead to problems down the road unless it follows a strict model
    > > allowing substitution, where each derived class has an "is-a"
    > > relationship with the base class.


    > > I was wondering, however, if implementation inheritance (private
    > > inheritance) might be a better idea in some cases. Consider the SGI C+
    > > + extension implementation of hash_set and hash_map. Both hash_set
    > > and hash_map use composition to reuse code from an internal class.
    > > They each have an internal hash_table class, which implements the
    > > basic functions of a hash table. The hash_set and hash_map class use
    > > delegation to access the functionality of the internal hash_table
    > > class. Google's sparse hash map/hash set also uses the same design
    > > scheme.


    > > This is a nice clean design, except one thing about it really bothers
    > > me. There's nothing preventing someone from instantiating an instance
    > > of the internal hash_table class somewhere else. Unlike an abstract
    > > base class, or a base class with a protected constructor, the internal
    > > hash_table "base" class can be instantiated anywhere, even though this
    > > would be useless.


    > So what if they can be instantiated, what harm would it do. As you say
    > it will probably be useless but you can't know the needs of every
    > developer out there.


    More to the point: if it's really useless, you don't have to do
    anything to prevent it, since no one will do it.

    In this case, there might be a case to argue that the base class
    isn't adequately documented for use by others. As far as I can
    tell, there's absolutely no guarantee that it will even be
    present in the next release, or have the same interface if it
    is. But again, I'd say that this is the user's problem. If one
    is stupid enough to use some undocumented interface, then one
    deserves whatever happens. (And realistically, there are many
    cases where you cannot really avoid it.)

    > I think this is kind of making it impossible to
    > inherit from a class, I can't see any need for it. All it would
    > accomplish would be to prevent possible ways of implementation.


    > Since you can't anticipate all the requirements that might be
    > placed on your application in the future you should try to not
    > artificially limit the extensibility of your code (unless it
    > makes it easier to satisfy the current requirement).


    You're code is really only extensible in ways you've planned for
    and documented. But let's face it, only a fool would try to use
    something that wasn't planned for and documented. (It's not
    as though you might accidentally use it, as a result of a typo.)

    --
    James Kanze (Gabi Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jul 29, 2007
    #8
  9. James Kanze Guest

    On Jul 29, 12:30 am, wrote:
    > I suppose I tend to think that, from a design point of view, if it
    > doesn't make any sense to instantiate a certain class outside of
    > another class, than this should be reflected somehow in the code, e.g.
    > by having a protected constructor.


    The usual way is by encapsulating it in something like:
    //!@implementation
    // class definition here...
    //!@end
    That way, it doesn't show up in the documentation, and no one
    is even aware of it's existance.

    --
    James Kanze (Gabi Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jul 29, 2007
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. -
    Replies:
    1
    Views:
    491
    John C. Bollinger
    Apr 11, 2005
  2. Code4u
    Replies:
    9
    Views:
    2,801
  3. Ross A. Finlayson

    Composition hierarchy implementation?

    Ross A. Finlayson, Apr 5, 2008, in forum: C++
    Replies:
    2
    Views:
    772
    Ross A. Finlayson
    Apr 7, 2008
  4. Paul Butcher
    Replies:
    12
    Views:
    764
    Gary Wright
    Nov 28, 2007
  5. David B.
    Replies:
    6
    Views:
    160
    Panda Beer
    Jan 6, 2009
Loading...

Share This Page