Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Composition versus Implementation Inheritance

Reply
Thread Tools

Composition versus Implementation Inheritance

 
 
chsalvia@gmail.com
Guest
Posts: n/a
 
      07-28-2007
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?

 
Reply With Quote
 
 
 
 
Daniel T.
Guest
Posts: n/a
 
      07-28-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) 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.
 
Reply With Quote
 
 
 
 
=?ISO-8859-1?Q?Erik_Wikstr=F6m?=
Guest
Posts: n/a
 
      07-28-2007
On 2007-07-28 08:21, (E-Mail Removed) 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
 
Reply With Quote
 
chsalvia@gmail.com
Guest
Posts: n/a
 
      07-28-2007
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.



 
Reply With Quote
 
Daniel T.
Guest
Posts: n/a
 
      07-28-2007
(E-Mail Removed) 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.
 
Reply With Quote
 
chsalvia@gmail.com
Guest
Posts: n/a
 
      07-29-2007
On Jul 28, 6:53 pm, "Daniel T." <(E-Mail Removed)> 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.

 
Reply With Quote
 
Daniel T.
Guest
Posts: n/a
 
      07-29-2007
(E-Mail Removed) wrote:
> "Daniel T." <(E-Mail Removed)> 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.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      07-29-2007
On Jul 28, 3:39 pm, Erik Wikström <(E-Mail Removed)> wrote:
> On 2007-07-28 08:21, (E-Mail Removed) 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: (E-Mail Removed)
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

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      07-29-2007
On Jul 29, 12:30 am, (E-Mail Removed) 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: (E-Mail Removed)
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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Implementation of Aggregation and Composition David B. Ruby 6 01-06-2009 08:40 PM
Re: Mozilla versus IE versus Opera versus Safari Peter Potamus the Purple Hippo Firefox 0 05-08-2008 12:56 PM
Composition hierarchy implementation? Ross A. Finlayson C++ 2 04-07-2008 09:44 AM
equal? versus eql? versus == versus === verus <=> Paul Butcher Ruby 12 11-28-2007 06:06 AM
Private access modifier and Inheritance (Inheritance implementation in Java) maxw_cc Java 1 12-21-2003 11:38 AM



Advertisments