From: DN
To: Editor
I guess everyone somehow feels the need to weigh in on this,
so I won't be resisting the temptation.
Trying to step back from the discussion a bit, it seems that
the disagreement does from a large part stem from the difference of
perspectives--one of a perfectly logic world where everything is as it seems,
and the other based in the less-than-perfect reality of a particular
implementation of a particular model of type inheritance.
Despite your insistence that your original article is not an
attack on C++ in particular, the problem is one that stems from how C++ defines
inheritance (it is probably a reasonable guess that most OOPLs share, as far as
it is relevant, the same model, but not pretending to be an expert in other
OOPLs I will restrict my remarks to C++). In particular, inheritance does not
accurately model subtypes, nor do I believe it is necessary for it do so. C++
has no keyword that says "A is a subtype of B". It has a keyword (well,
actually a symbol, i.e. the humble colon!) that says A must support all the
operations and contains all the data associated with B. By this definition,
circle cannot inherit from ellipse, no matter how plainly obvious it is that a
circle is a type of ellipse. The problem is that for a number of cases C++
inheritance can model subtypes, and sometimes, particularly for the
uninitiated, it is the easiest or most obvious way to explain it. But to
pretend that it is designed for this purpose is to fool oneself, and the
circle/ellipse dilemma perfectly demonstrates this.
A model of inheritance whose purpose was to model subtyping
would, as you suggest, have to be somewhat different. It would say "A must
support all the read-only operations of B", and nothing much more. While
that solves the subtyping problem, it would be relatively useless in an OOPL.
It could be added as an extra "method" of inheritance, but I doubt it
would find too much use in real applications. It is still not entirely satisfying,
as it would require a circle to support the read-only operations "get
major axis" and "get minor axis", which are not operations one
would ever expect to perform on something you knew already was a circle. But if
C++ supported this form of inheritance, then this is exactly what you would use
to model the concept "a circle is a special type of ellipse". C++
does not have this form of inheritance, nor any easy way to model this concept,
so the easy solution is simply not to model this concept. In reality, it is of
dubious use in an application. The typical case of a drawing program is simply
not going to care whether something is a circle or an ellipse, in fact I know
of no drawing program that treats them differently (often there is a key you
hold down to "constrain" an ellipse to be circular, but after that
you wouldn't, for example, expect to see a description of the object declaring
it to be a circle with such and such a radius).
There may, of course, be possible applications where the
distinction is useful, but in all my C++ programming years I have never come
across this, or a similar problem. I suspect there is only so much breath (as
it were) wasting on the subject!
Chris Date Responds: DN wrote a pleasant and unusually
coherent commentary on the circles-and-ellipses debate. Indeed, I found myself
in considerable sympathy with much of DN's main argument. To paraphrase
somewhat, that argument was that C++ and other OO languages aren't really trying
to deal with subtyping in their approach to inheritance--that's not what they
want to do. In other words, they're more interested in software engineering
matters--in particular, with such issues as code reuse--and not so interested
in "models of reality" as such (this latter, perhaps being a matter
of more interest to database professionals).
However, DN then went on to say that "A model of
inheritance whose purpose was to model subtyping ... would be relatively
useless in an OOPL ... There may, of course, be cases where [such a facility]
is useful, but in all my C++ programming years I have never come across
this." There are a couple of (major) points I want to make in response to
these remarks:
First, Hugh Darwen and I have never claimed that our brand of
type inheritance would be useful "in an OOPL." Au contraire,
in fact: We recognize that our brand of inheritance doesn't work with
objects (at least inasmuch as one can agree on what "objects" are).
To be specific, if using "an OOPL" means using objects that have
object IDs, then we recognize that specialization by constraint (S by C)
and generalization by constraint (G by C)--see my response to KU
earlier--can't be made to work. Since we regard S by C and G by C as
essential components of a good model of subtyping and inheritance, we conclude
that "OOPLs" (or objects) and a good model of subtyping and
inheritance are incompatible concepts. This is one of several reasons why we
reject objects, as such, entirely in THE THIRD
MANIFESTO (see Appendix G of the book for arguments and examples
in support of the foregoing position.)
Second, there's an implicit wider suggestion in DN's letter
(possibly unintended) to the effect that a model of inheritance whose purpose
was to model subtyping would be relatively useless in general (i.e., not
just "in an OOPL"). Well, here I'd like to observe that, in sharp
contrast with this position, Hugh Darwen and I have discovered the
following.
a.
Our brand of inheritance provides an elegant solution to a
certain problem that arises in connection with something we're currently very
interested in: namely, the proper handling of temporal data. What's
more, we haven't seen any other "good" solution to the problem in
question in the literature.
b.
Our brand of inheritance also deals elegantly with a somewhat
vexing problem that arises in connection with questions such as this one: Are
NUMERIC(3) and NUMERIC(2) different types or not?
c.
Preliminary investigations seem to show that our brand of
inheritance also provides an elegant approach to certain important problems
that arise in the world of geospatial applications.
(We plan to publish our thoughts on these matters as soon as
we can, but don't hold your breath.)
Finally, let me add that we can do "C++-style
inheritance" in our model; we just don't call it inheritance (or
subtyping). In fact we don't explicitly call it anything at all, but what I
have in mind is akin to what I believe some people call delegation. Appendix
F of the book already mentioned gives some examples; Appendix G also
discusses the issue.
Posted
05/03/02
[ABOUT]
[QUOTES]
[LINKS]