[comp.object] Understanding the Object-Oriented Life-Cycle

aihaug@AUSTIN.LOCKHEED.COM (Daniel A Haug) (11/10/89)

In article <5026@internal.Apple.COM>, chewy@apple.com (Paul Snively) writes:

> Speaking of criticisms, I'm interested in a good discussion on why 
> statically-typed hybrid languages like Object Pascal and C++ aren't useful 
> in some contexts where dynamically-typed languages such as Common Lisp 
> w/CLOS are.  Any takers?

Having just completed a project with 100+ thousand lines of
CLOS-based code, yeah I can think of a few places where dynamic
typing was useful... and a few dozen other things that would
have made this project VERY hard in C++.

By far (IMHO), the largest advantage to this is in code extensibility,
or reusability.  It is so incredibly useful to define an algorithm
that doesn't care about the types on which it operates.  For example,
I need only implement a priority queue ADT once.  The algorithm is the
same, but the types can be whatever.  As result, I only need to write
one QUEUE and DEQUE procedure that don't depend on any typing.  Then,
every object that is passed into the queue would need to support 
some sort of comparison method that QUEUE would call to determine
proper placement.

Although you, Paul, have barked at people referring to Lisp as
typeless (understandably), I still think of this as being an example
of a typeless function.  The functions QUEUE and DEQUE know nothing
about the types of objects on which they are operating.  This is VERY
typical of the style of design in our applications.  The ability to
reuse major segments of code because of their `typeless' characteristics
saved us man-years of effort.

----------

On a naive note, does C++ or any other C-based OO extensions support
different types of method combination?  In our applications, we only
used this capability in CLOS a few times.  However, it was immensely
useful when we DID use it.

-- 
Internet: haug@austin.lockheed.com
UUCP:     ut-emx!lad-shrike!aihaug

sidney@saturn.ucsc.edu (Sidney Markowitz ) (11/10/89)

aihaug@AUSTIN.LOCKHEED.COM (Daniel A Haug) writes (in comp.object):
>
>On a naive note, does C++ or any other C-based OO extensions support
>different types of method combination?

I, too, come from a Lisp background. Would someone with more C++
experience please comment on the accuracy of the following?
(Note: If you don't know better, please don't assume the following is
true - I'm really asking a question):

My reading of the spec is that C++ has no method combination. If a
derived class has a member function of the same name as a member
function of a base class, only the derived class's member function is
used when it is called. With multiple inheritance, if there's more
than one base class with a member function of a certain name, then
either the derived class has to also have a member function defined
with that name, or any call to that function for an instance of that
class has to be explicitly qualified by the name of one of the base
classes.

Using the non-C++ terminology I'm more familiar with, I would say it
this way:

If you have child class CH1 inheriting from parent classes P1 and P2,
and V1 is an instance of CH1, then

If P1 has a method foo, you can call V1.foo() and it will refer to the
method defined on P1, i.e., P1::foo. If P2 also has a method foo, then
V1.foo() will generate a compile-time error since it is ambiguous.
However if CH1 has a method foo defined then V1.foo() will always be
legal and will refer only to CH1::foo. In that case, to refer to the
foo methods of the parents, you would have to say things like
P1::foo(V1) or P2::foo(V1).

-- sidney markowitz <sidney@saturn.ucsc.edu>

joel@nastar.UUCP (Joel Rives) (11/10/89)

>aihaug@AUSTIN.LOCKHEED.COM (Daniel A Haug) (aihaug@AUSTIN.LOCKHEED.COM, <315@shrike.AUSTIN.LOCKHEED.COM>):
>By far (IMHO), the largest advantage to this is in code extensibility,
>or reusability.  It is so incredibly useful to define an algorithm
>that doesn't care about the types on which it operates.  For example,
>I need only implement a priority queue ADT once.  The algorithm is the
>same, but the types can be whatever.  As result, I only need to write
>one QUEUE and DEQUE procedure that don't depend on any typing.  Then,
>every object that is passed into the queue would need to support 
>some sort of comparison method that QUEUE would call to determine
>proper placement.

Perhaps, i am misunderstanding the point you are making here. It is not at
all difficult to code a QUEUE object in C++ that will accept a generic 
reference upon which to operate. A new instantiation of this QUEUE object
could be passed a comparison function when created that would be specific
to the data type being queued. Actually, i can think of a couple of different
ways to approach this problem --largely asthetic in their differences. As in
the above example, the algorithm need be coded only once.

Joel

ttwang@polyslo.CalPoly.EDU (Thomas Wang) (11/11/89)

aihaug@AUSTIN.LOCKHEED.COM (Daniel A Haug) writes:
>In article <5026@internal.Apple.COM>, chewy@apple.com (Paul Snively) writes:

>Having just completed a project with 100+ thousand lines of
>CLOS-based code, yeah I can think of a few places where dynamic
>typing was useful... and a few dozen other things that would
>have made this project VERY hard in C++.

C++ has run-time binding virtual functions, but that is not exactly
run-time binding data objects.  I think run-time binding functions have less
overhead, but force the programmers to make early decisions about how the
function call formats look like.

>On a naive note, does C++ or any other C-based OO extensions support
>different types of method combination?

What is method combination?  I am interested to know.
 
>Internet: haug@austin.lockheed.com

 -Thomas Wang (Ah so desu ka!)

                                                     ttwang@polyslo.calpoly.edu

thant@horus.esd.sgi.com (Thant Tessman) (11/11/89)

In article <654@nastar.UUCP>, joel@nastar.UUCP (Joel Rives) writes:
> >aihaug@AUSTIN.LOCKHEED.COM (Daniel A Haug) (aihaug@AUSTIN.LOCKHEED.COM, <315@shrike.AUSTIN.LOCKHEED.COM>):
> >By far (IMHO), the largest advantage to this is in code extensibility,
> >or reusability.  It is so incredibly useful to define an algorithm
> >that doesn't care about the types on which it operates.  For example,
> >I need only implement a priority queue ADT once.  The algorithm is the
> >same, but the types can be whatever.  As result, I only need to write
> >one QUEUE and DEQUE procedure that don't depend on any typing.  Then,
> >every object that is passed into the queue would need to support 
> >some sort of comparison method that QUEUE would call to determine
> >proper placement.
> 
> Perhaps, i am misunderstanding the point you are making here. It is not at
> all difficult to code a QUEUE object in C++ that will accept a generic 
> reference upon which to operate. A new instantiation of this QUEUE object
> could be passed a comparison function when created that would be specific
> to the data type being queued. Actually, i can think of a couple of different
> ways to approach this problem --largely asthetic in their differences. As in
> the above example, the algorithm need be coded only once.
> 
> Joel

I am just catching the beginning of this thread so pardon my ignorance if
this has already been hashed out.

I think the first poster is refering to a rather large hole in C++ that 
hopefully will be plugged by the implementation of parameterized types.

Yes, you can implement generic lists and queues in C++ that don't care
what they contain, but the implementation is either not type safe, or
faked using macros.  (See _Programming in C++_ by Dewhurst and Stark for
an interesting way to use macros to create generic container classes.)

Another trick I (and probably many others) use is to inherit link-listability,
(or queueability) from a base class and then make the iterator function (e.g.
'next' or '++') a virtual and overload it to make it return the correct
type.  This solution is easy if you know the things will only be in 
one list at a time, and "possible" :-) if the things need to be in multiple
lists or queues at a time.

Unfortunately, these are all 'tricks' and not C++ proper.

Even Stroustrup acknowledges 'parameterized types' as an aspect of 
Object-Oriented Programming that is orthogonal to 'inheritance,' 
'data abstraction,' etc.

thant

P.S.  I do think that C++ is truely a bitchin' language and wouldn't 
use anything else.
--
There are 336 dimples on the standard golf ball.

aihaug@AUSTIN.LOCKHEED.COM (Daniel A Haug) (11/11/89)

In article <654@nastar.UUCP>, joel@nastar.UUCP (Joel Rives) writes:
> Perhaps, i am misunderstanding the point you are making here. It is not at
> all difficult to code a QUEUE object in C++ that will accept a generic 
> reference upon which to operate. A new instantiation of this QUEUE object
> could be passed a comparison function when created that would be specific
                                                     ^^^^^^^^^^^^^^^^^^^^^^
> to the data type being queued. Actually, i can think of a couple of different
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> ways to approach this problem --largely asthetic in their differences. As in
> the above example, the algorithm need be coded only once.
> 
> Joel

For many of our particular applications, this is overly restrictive.
I may very well want a single queue to hold objects of vastly different
types.  Perhaps I'm wrong (and often am ;-), but I don't see how to
accomplish this in a statically typed language.

dan haug
-- 
Internet: haug@austin.lockheed.com
UUCP:     ut-emx!lad-shrike!aihaug

pwasilko@rodan.acs.syr.edu (Wasilko) (11/11/89)

Newsgroups: comp.object
Subject: Re: Understanding the Object-Oriented Life-Cycle
Summary:
Expires:
References: <5026@internal.Apple.COM> <315@shrike.AUSTIN.LOCKHEED.COM> <654@nastar.UUCP> <317@shrike.AUSTIN.LOCKHEED.COM>
Sender:
Reply-To: pwasilko@rodan.acs.syr.edu (Wasilko)
Followup-To:
Distribution:
Organization: Syracuse University, Syracuse, NY
Keywords:

In article <317@shrike.AUSTIN.LOCKHEED.COM> aihaug@AUSTIN.LOCKHEED.COM (Daniel A Haug) writes:
>In article <654@nastar.UUCP>, joel@nastar.UUCP (Joel Rives) writes:
>> Perhaps, i am misunderstanding the point you are making here. It is not at
>> all difficult to code a QUEUE object in C++ that will accept a generic
>> reference upon which to operate. A new instantiation of this QUEUE object
>> could be passed a comparison function when created that would be specific
>                                                     ^^^^^^^^^^^^^^^^^^^^^^
>> to the data type being queued. Actually, i can think of a couple of different
>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> ways to approach this problem --largely asthetic in their differences. As in
>> the above example, the algorithm need be coded only once.
>>
>> Joel
>
>For many of our particular applications, this is overly restrictive.
>I may very well want a single queue to hold objects of vastly different
>types.  Perhaps I'm wrong (and often am ;-), but I don't see how to
>accomplish this in a statically typed language.
>
>dan haug
>--
>Internet: haug@austin.lockheed.com
>UUCP:     ut-emx!lad-shrike!aihaug

In Object Pascal I achieve the generic ADT effect by creating a single base-
class called anObject with special clone, free, and key methods.  The clone
method duplicates the object and is overridden by each subclass to also copy
any objects stored in them.  Each object in the class anObject also holds a
referenceCount variable that I use with the free method for automatic garbage
collection.  Ie. in any arbitrarily complex strucure each time I add an object
I increment the referenceCount and when I remove an object I call free which
will Dispose of the object only if the referenceCount - 1 is zero, otherwise
it decrements the referenceCount.  To deal with cyclic structures, each object
has a marked flag that is set by free, as free trys to delete subobjects it
checks each to see if it is marked.  If it is it just decrements that objects
referenceCount and detaches it from the structure.  ADT all take items of class
anObject and call Key for any positional comparisons.  For every subclass Key
is overridden to produce a sensible string value.  Thus class anInteger sets
Key to the text representation of the actual number.

This aproach is far from elegant and requires the clone, free, and key methods
to be overriden for all subclasses, but it does let me work with generic ADT's
that I need only define once.  If you have any better aproaches for Object
Pascal please feel free to let me know...

Peter J. Wasilko                |        I'm not stupid, I'm not expendable,
SU Law '91                        |           and I'm not going --- Avon
JWasilko@Sunrise.Acs.Syr.Edu        |

sdm@brunix (Scott Meyers) (11/11/89)

In article <44454@sgi.sgi.com> thant@horus.esd.sgi.com (Thant Tessman) writes:
>Yes, you can implement generic lists and queues in C++ that don't care
>what they contain, but the implementation is either not type safe, or
>faked using macros.  (See _Programming in C++_ by Dewhurst and Stark for
>an interesting way to use macros to create generic container classes.)
>
>Another trick I (and probably many others) use is to inherit link-listability,
>(or queueability) from a base class and then make the iterator function (e.g.
>'next' or '++') a virtual and overload it to make it return the correct
>type.  This solution is easy if you know the things will only be in 
>one list at a time, and "possible" :-) if the things need to be in multiple
>lists or queues at a time.

Hmmm, what about using MI so that anything that will ever go on a list
inherits from a class "Listable" that defines the appropriate virtual
comparison operators?  Then your lists would consist of pointers to objects
of type Listable.  It should be type-safe because only Listable objects can
end up on lists, and all Listable objects have the necessary comparison
operators appropriately defined.  No macros needed, and having a single
object on multiple lists is no problem.  Am I overlooking something?

Scott
sdm@cs.brown.edu

kcr@netxdev.DHL.COM (Ken Ritchie) (11/11/89)

I'll help pay the phone bills before I'll drop out... and I heartily endorse
Ed (Berard) for his initiative in forming comp.object (and his generous notes).

Just like the folks at Mars' Hill (the Areopagus) in Acts 17:21, we LIKE TO
converge here to discuss the latest new ideas and learn from each other...
after all, this is an elective subscription, isn't it?

Ed is so polite -- he always says "Thanks for listening!" -- and he does
include very useful notes, often WITH A BIBLIOGRAPHY!  And, you can even
talk back to him... or phone him!  I hope I speak for MANY OF US, when I say...

>>>--->   Ed: Thanks for writing!  [Your fan club is not the empty set!]

_______________________________________________________________________________

Ken Ritchie (a.k.a. kcr)		Usenet:	...!uunet!netxcom!netxdev!kcr
NetExpress Communications, Inc.		
1953 Gallows Rd, Suite 300		FAX:	USA (703) 749-2375
Vienna, Virginia (USA) 22182		Voice:	USA (703) 749-2268
_______________________________________________________________________________

chewy@apple.com (Paul Snively) (11/12/89)

In article <315@shrike.AUSTIN.LOCKHEED.COM> aihaug@AUSTIN.LOCKHEED.COM 
(Daniel A Haug) writes:
> Although you, Paul, have barked at people referring to Lisp as
> typeless (understandably), I still think of this as being an example
> of a typeless function.  The functions QUEUE and DEQUE know nothing
> about the types of objects on which they are operating.  This is VERY
> typical of the style of design in our applications.  The ability to
> reuse major segments of code because of their `typeless' characteristics
> saved us man-years of effort.

Understood and agreed; my "barked" point was that in Lisp, it's actually 
data that has type, not variables, which as far as I'm concerned is as it 
should be.  Sorry if I sounded like I was being too curmudgeonly! :-)

In article <315@shrike.AUSTIN.LOCKHEED.COM> aihaug@AUSTIN.LOCKHEED.COM 
(Daniel A Haug) writes:
> On a naive note, does C++ or any other C-based OO extensions support
> different types of method combination?  In our applications, we only
> used this capability in CLOS a few times.  However, it was immensely
> useful when we DID use it.

For us Macophiles, there's OIC (Objects In C), by John Wainwright.  He's 
written a set of extensions to THINK C that are based on-guess 
what?--CLOS.  He even tosses in a 15K Lisp interpreter so that you can a) 
play with his stuff interactively, b) add scripting to your applications.  
I like it a lot.

__________________________________________________________________________
Just because I work for Apple Computer, Inc. doesn't mean that they 
believe what I believe or vice-versa.
__________________________________________________________________________
C++ -- The language in which only friends can access your private members.
__________________________________________________________________________

dlw@odi.com (Dan Weinreb) (11/13/89)

In article <9707@saturn.ucsc.edu> sidney@saturn.ucsc.edu (Sidney Markowitz ) writes:

   My reading of the spec is that C++ has no method combination. 

That's right, and everything else in your posting is right as far as
my understanding goes.

Dan Weinreb		Object Design, Inc.		dlw@odi.com

thant@horus.sgi.com (Thant Tessman) (11/14/89)

In article <20481@brunix.UUCP>, sdm@brunix (Scott Meyers) writes:
> Hmmm, what about using MI so that anything that will ever go on a list
> inherits from a class "Listable" that defines the appropriate virtual
> comparison operators?  Then your lists would consist of pointers to objects
> of type Listable.  It should be type-safe because only Listable objects can
> end up on lists, and all Listable objects have the necessary comparison
> operators appropriately defined.  No macros needed, and having a single
> object on multiple lists is no problem.  Am I overlooking something?
> 
> Scott
> sdm@cs.brown.edu

I don't know.  I think what you describe is fine for doing 'listy' type things
on lists.  But, in my case, what I really wanted was a list of Goobers that 
I could do 'goobery' things with as well as 'listy' things.  In that case, I
needed to overload my iterator to return the correct type.  This guarantees
that I can't to 'goobery' things to any old list, just to lists of
Goobers.  Since 
List was a base class of Goober (I didn't really call it Goober) all the
list stuff
automatically worked and was type safe.

And even this won't solve the problem of allowing a list where each element 
can be anything.  (I don't even think dynamic typing is a solution.  What 
does the program written in a dynamic typing language do when the type 
is wrong that you couldn't get a c++ program to do just as easily?)

thant

--------------------------

There are 336 dimples on the standard golf ball.

yost@esquire.UUCP (David A. Yost) (11/14/89)

In article <315@shrike.AUSTIN.LOCKHEED.COM> aihaug@AUSTIN.LOCKHEED.COM (Daniel A Haug) writes:
>In article <5026@internal.Apple.COM>, chewy@apple.com (Paul Snively) writes:
>
>> Speaking of criticisms, I'm interested in a good discussion on why 
>> statically-typed hybrid languages like Object Pascal and C++ aren't useful 
>> in some contexts where dynamically-typed languages such as Common Lisp 
>> w/CLOS are.  Any takers?
>
>By far (IMHO), the largest advantage to this is in code extensibility,
>or reusability.  ... For example, I need only implement a priority queue
>ADT once.  The algorithm is the >same, but the types can be whatever.

Of course, someone has to say (I'll volunteer) that the following
language attributes are in principle orthogonal:
 1.  statically-typed
 2.  hybrid languages like Object Pascal and C++
 3.  genericity (also known as parameterized types)

You are asking for #3.  C++ has 1 (with escape
mechanisms), 2, and a kluged 3-workaround with
promises of real 3 'real soon now' (my guess 1992).
There do exist languages that have 1 and 3.  Eiffel
for one, and it goes so far as to provide for generic
class parameters to be constrained to be descendants
of a specific type, which you need for static type
checking.  For example,
    HASH_TABLE [ T -> HASHABLE ]
    SORTED_LIST [ T -> COMPARABLE ]
    etc.

 --dave yost

ewan@cs.washington.edu (Ewan Tempero) (11/17/89)

In article <315@shrike.AUSTIN.LOCKHEED.COM> aihaug@AUSTIN.LOCKHEED.COM (Daniel A Haug) writes:
>By far (IMHO), the largest advantage to this is in code extensibility,
>or reusability.  It is so incredibly useful to define an algorithm
>that doesn't care about the types on which it operates.  For example,
>I need only implement a priority queue ADT once.  The algorithm is the
>same, but the types can be whatever.  As result, I only need to write
>one QUEUE and DEQUE procedure that don't depend on any typing.  Then,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>every object that is passed into the queue would need to support 
>some sort of comparison method that QUEUE would call to determine
>proper placement.

But QUEUE and DEQUE aren't operations on _elements in the priority
queue_! They are operations on objects of type "priority queue". So
there is nothing "typeless" about them at all, you have just been
using the wrong type. Many people seem to have this misconception
which I think may be due to Pascal including the type of the
element as part of the type of the array. There is a (OO) programming
language called Emerald  whose type system will allow you to do
what you require. See "Distribution and Abstract Types in Emerald"
by Black, Hutchinson, Jul, Levy, and Carter. Trans. Software 
Engineering, Dec 1986.
--ewan

ewan@cs.washington.edu (Ewan Tempero) (11/17/89)

In article <9828@june.cs.washington.edu> ewan@june.cs.washington.edu.cs.washington.edu (Ewan Tempero) writes:
>See "Distribution and Abstract Types in Emerald"
>by Black, Hutchinson, Jul, Levy, and Carter. Trans. Software 
>Engineering, Dec 1986.
Sorry, this should be Trans. Software Engineering, Jan 1987. Vol 13(1):65-76
(it was a special issue on Distributed Computing). 
--ewan