Hi JAL,
Yes, but the question I asked is WHY would someone want to design a
completely sealed class? In what SPECIFIC scenario would it be 'dangerous'
to allow a class to be inherited, and WHY would it be dangerous in that
scenario? In describing why it would be dangerous, please say why 'private'
and not creating virtual methods are insufficient tools to cause the class
to be 'sealed enough'? That is, if I make all the public methods non-virtual
and everthing else private, where is the harm of allowing inheritance from
such a class (in contrast to sealing it)?
---
I've read parts of the article you pointed to (but not all of it). First, it
was written 19 years ago, and things have changed! Next, the article seems a
bit 'strawman' in its arguments.
For example, it uses the construction of two classes, 'stack' and 'deque'
for illustrative purposes. Quickly, a 'deque' is a 'stack' that can 'put'
and 'get' elements to/from both ends, while 'stack's can only do this at one
end. The author then says that 'stack' should inherit from 'deque' (!!!!),
that to do this the access to the methods to deal with the 'other end'
should be suppressed in 'stack', and then says this shows inheritance
weakens encapsulation since one should never remove the external interface
to the base class (i.e., derived classes should preserve the base class
interface, which I totally agree with).
But, he has it backwards. 'Deque' should inherit from 'stack' and ADD the
'back-end' functionality! IMHO, it's good programming practice to have base
classes only contain methods which apply to EVERYTHING that can derive from
it, since like the author and I do agree upon (and bears repeating),
"derived classes should preserve the base class interface". Thus, in the
author's example, he made a poor choice in 'deque' as a bases class if he
wanted to derive 'stack' from it.
The author also seems to think that derived classes have access to
everything in its base class - was this article written before 'private' was
invented? Here is a quote from the article that definitely seems to indicate
'private' was not in the author's knowledge base:
"In most obect-oriented languages, tile code of a class may directly access
all the instance variables of its objects, even those instance variables
that were defined by the ancestor class. Thus, the designer of a class is
allowed full access to the representation defined by the ancestor class."
And if a base method is NOT declared as virtual, it is sealed as far as any
derived class is concerned (at least as far as it's particular calling
sequence is defined, overloads are really new methods that just happen to
have the same name for convenience). To me 'sealed' seems like a lazy way
allowing the covering up of poor design choices when it comes to heirarchial
structure, and are usually caused by incorrectly encapsulating members and
methods via the use of 'private', and incorrect use of 'virtual'.
So, IMHO, this article does not convince me that any class should ever be
'sealed' (that is, prevented from being derived from). Ok, MAYBE a class
designed for SECURITY (e.g., DES algorithm), but I'd have to think about
that as well...
---
Now, if the new 'dialect' of C++ introduced with VS C++.NET 2005 has
included tools that allow violation of 'private', then the problem lies in
these new tools, not the concept of inheritance vs. encapsulation...
[==P==]
JAL said:
Peter.... If you specifically design a class for inheritance as in
CollectionBase, I see no problem. Here is the paper:
http://72.14.203.104/search?q=cache...er.pdf+snyder+inheritance+encapsulation&hl=en
Peter Oliphant said:
Inheritance can't break encapsulation if encapsulation is done correctly.
That's what 'private' vs. 'protected' and 'virtual' vs. 'non-virtual'
are
all about (at least I thought so)...
[==P==]
Peter.... I can't speak to the ImageList example, but Snyder has argued
that
if a class was not designed to be extended it should be sealed. The
reason
is
that "inheritance breaks encapsultation." You can still use composition
as
in
Joshua Blocks "prefer composition over inheritance".
:
I just discovered that the ImageList class can't be inherited. Why?
What
could go wrong? I can invision a case where someone would like to add,
say,
an ID field to an ImageList, possible so that the individual elements
in
an
array of ImageList's could be identified by the ID, thereby allowing
re-ordering the array without harm. A person could identify by index
into
the array, but that would not be preserved by re-ordering (and
re-ordering
makes sense if one removes one of the ImageList's in the array). But
without
the ability to inherit ImageList, now one must design a new a class
with
an
ImageList member and an ID member. This wouldn't be a big deal, but
now
to
expose the public methods of the contained ImageList one must either
expose
the member itself or manually expose the various innate features of an
ImageList. This is done automatically if one is allowed to inherit
ImageList
in a 'public' way.
Now that's just an exampe with ImageList, and ID is not a good
example, I
just used it to make my point. In general, it seems odd one would want
to
prevent any class from being inherited. I can see preventing the
overriding
or overloading of some class methods and keeping some members private.
But
complete denial? Why?
[==P==]