Newsgroups: comp.object,comp.lang.smalltalk,comp.lang.ada,comp.lang.c++
Path: cantaloupe.srv.cs.cmu.edu!europa.chnt.gtegsc.com!howland.reston.ans.net!math.ohio-state.edu!uwm.edu!fnnews.fnal.gov!gw1.att.com!news.bu.edu!inmet!houdini!stt
From: stt@houdini.camb.inmet.com (Tucker Taft)
Subject: Re: Ada95 not OO (was Re: Has C++ had its day?)
X-Nntp-Posting-Host: houdini.camb.inmet.com
Message-ID: <DB9G0H.8H3@inmet.camb.inmet.com>
Followup-To: comp.object,comp.lang.smalltalk,comp.lang.ada,comp.lang.c++
Sender: news@inmet.camb.inmet.com (USENET news)
Organization: Intermetrics, Inc.
X-Newsreader: TIN [version 1.1 PL8]
References: <3t3mtb$i5@mail.one.net>
Date: Wed, 5 Jul 1995 20:38:41 GMT
Lines: 51
Xref: glinda.oz.cs.cmu.edu comp.object:34405 comp.lang.smalltalk:25502 comp.lang.ada:32140 comp.lang.c++:136774

In a short paper I wrote for OOPSLA a few years ago, I explained
the transition from Ada 83, which I called an "abstraction-oriented"
language, to Ada 95, which is (certainly ;-) an "object-oriented" language.

The main difference between an abstraction-oriented language
and an object-oriented language in my view was that in
an abstraction-oriented language, a given abstraction interface
has just one implementation, whereas in an object-oriented
language, a given abstraction interface may have many implementations.
The instances of the abstraction, i.e. the "objects," carry around
an identification of their implementation (this identification is called
a "tag" in Ada 95; it is the pointer to the virtual function table in
C++).  

In other words, multiple implementations per interface with
self-identifying objects is the key -- i.e. run-time polymorphism.
Either inheritance or delegation can be used to get reuse across
implementations, but without the polymorphism, both inheritance
and delegation are pretty boring.

By the way, although on first glance it might look like a package
is just a "namespace" in Ada, in fact, there is a very tight
connection between a type declared in a package spec,
and the operations on that type declared immediately in the same
package spec.  These operations are called the "primitive"
operations, and they are the (only) ones that are inherited
by derivatives of the type, and they are the (only) ones that
directly support run-time dispatching/polymorphism.  Operations on a type
declared elsewhere are not primitive, and not dispatching; such
nonprimitive operations are like regular top-level functions in
C++ -- they are not strongly associated with any particular type.

One of the main advantages of the Ada approach to defining primitive
operations is that binary operations are symmetric in their operands,
rather than requiring that the first operand be special in some way.
Note that it is common in C++ to declare all binary operators as friends
to get symmetry for the operands, but then of course you lose
inheritance.  In Ada, binary operators just "work" -- you get both
inheritance and symmetry.

Note also that fewer special prefixes are required in Ada than in C++ to 
distinguish between virtual, static, non-virtual/non-static, etc.  
The visibility and lifetime characteristics of an entity, be it a type, 
subprogram, or object, are determined by where it is declared, rather than 
by a variety of prefixes.  Something declared directly in a package lives
as long as the package; something declared inside a type lives as
long as the instance of the type; something declared inside a subprogram
lives as long as the execution of the subprogram.

-Tucker Taft
Intermetrics, Inc.
