🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sw.components
Article #357

Re: OOP and re-usable cakes

#357
From: Doug Lea
Date: Sun, 05 Aug 1990 12:50
120 lines
6846 bytes
> From: steve@taumet.com (Stephen Clamage)

> >rick@tetrauk.UUCP (Rick Jones) writes:

> >This approach doesn't always reflect reality, though.  You often do want an
> >inheritance which says "A is like B except ...", meaning the sub-class is NOT
> >going to conform to some aspects of its parent....
> 
> Again, you can do this in C++.  It is possible to eliminate some of a
> base (parent) class's functionality within a derived (sub) class.  You
> simply override the base class function in the derived class with an
> empty function which is private.

This is a TERRIBLE thing to do in any OOPL (like C++ and Eiffel) that
attempts to maintain some relation between subclassing and subtyping.
As Rick Jones says, it breaks conformance: If some base class Base
contains some method m that returns an int, perhaps with some promises
(postconditions) about the nature of the return value and/or the
resulting state of the object, and a derived class Derived redefines m
to simply abort execution or somesuch, then any polymorphic function
accepting argument b of type Base or subclass thereof, and calls b.m
may no longer be able to meet its own postconditions, since its
implicit preconditions (i.e., that b is an object containing method m
with specified behavior) are broken.

Rick is right that programmers do often wish to create a new class
B that is like some existing class A, except that it does not contain
one or more methods/features. Probably the most common case of this
is during the honorable activity of `retrospective abstraction', where
you find that a class was overdesigned and you need something with
fewer features; or that two previously unrelated classes could benefit
by being linked via a new common ancestor.

For among the simplest (perhaps least realistic) examples, suppose you
HAVE a Deque class lying around, but you NEED a simple Stack class.
The Deque contains methods push, pop, empty, rearpush, and rearpop.
For both safety and coherence reasons, you don't want to just use the
Deque as a Stack (since you want to guarantee that pushrear is NEVER
called). But if you create class Stack as a subclass of Deque by
nulling out rearpush and rearpop, you open up the Stack component to
misuse: Sending a Stack to any function expecting a Deque might result
in unexpected behavior like a core dump.

In fact, it is easy to see that Stack is a SUPERclass of Deque. A
Deque may be safely used wherever a Stack is expected. No `common'
OOPLs allow you to RETROSPECTIVELY state this in any way short of
redesigning the heirarchy. 

However, support for such constructs is not a completely novel idea:
Retrospective superclassing is nearly the same notion as `views' in
OBJ (see any of Goguen's recent papers) and LILEANNA (an Ada
tool/preprocessor described by W. Tracz in his in-progress thesis) and
`reductions' in Alberich (see July '90 SIGPLAN notices article by
Paaki et al). It is also possible to get this effect in languages
based on implicit conformance-checking rather than explicit
subtyping/subclassing, e.g., Quest (see Cardelli's DEC-SRC TRs), and
to some extent, Emerald/Jade (see Raj & Levy's ECOOP '89 paper).

What might an OOPL supporting `views' (I'll stick to that term) look like?

First, and most importantly, it MUST allow (even nicer: mandate) the
separation of type specification (i.e., declaration of method
argument and return types, perhaps with pre- and post-conditions) from
class implementation (i.e., member data and code needed to carry out
these specs). 

It is possible to maintain this separation via the convention of using
`Abstract' or `Deferred' classes in C++, Eiffel, and other languages,
or via more direct support found in Johnson's Typed Smalltalk (TS) and
Emerald.

This separation is necessary in order to ensure that a new view is
properly self-contained. For example, if the Deque class, above, mixed
specification and implementation, it might be the case that
Deque::push was implemented by calling Deque::rearpush when the Deque
is empty. A Stack view of the Deque that omits rearpush would then
fail to even make sense.

The consensus these days seems to be that such separation is a Good
Thing anyway: it allows specifications to be realized via multiple
implementations with different performance characteristics; it allows
independent reuse of either specifications or implementations; and
allows independent extensions of both types and implementations.

However, separation of specification and implementation can make it
hard to reuse implementations without further aids. A composition
mechanism similar to that of Emerald/Jade that is equally useful for
both composing and splitting apart implementations would be a valuable
adjunct.  Alternatively, the implementation side might even employ a
form of prototyping/delegation (as in SELF) instead of subclassing or
composition: Separating specifications from implementations allows the
design and coding tools/constructs to vary independently.

There are a number of other interesting issues as well. Among them:

*) Renaming: Suppose the Deque method to place things on the front
    was called `frontpush', but you'd like it to be called just `push'
    in the Stack view. Is this OK?

*) Multiple views: A Deque can be view'd as a Stack in either of 
    two ways (using the Deque push/pop pair OR the rearpush/rearpop 
    pair to perform Stack push/pop). Can more than one view be supported?

*) Structure: Programs written with views might be hard to read since 
    new superclasses can be declared on the fly. Tools are needed to
    reconstruct/fake the underlying hierarchical design.

*) And a host of implementation matters ...

Are views important enough constructs to warrant creation of new
languages or tools? (All of the above COULD be incorporated into a
front-end design tool/preprocessor for C++, Smalltalk, SELF or nearly
any other OOPL.)

-Doug
--
Doug Lea, Computer Science Dept., SUNY Oswego, Oswego, NY, 13126 (315)341-2688
email: dl@g.oswego.edu            or dl@cat.syr.edu
UUCP :...cornell!devvax!oswego!dl or ...rutgers!sunybcs!oswego!dl
Technical Details
Message-ID: <DL.90Aug5085427@g.g.oswego.edu>
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!news-server.csri.toronto.edu!mailrus!cs.utexas.edu!rutgers!ub!oswego!news
References: <27705@athertn.Atherton.COM> <71800004@m.cs.uiuc.edu> <620@.tetrauk.UUCP> <7057.26b57e9c@swift.cs.tcd.ie> <707@tetrauk.UUCP> <382@taumet.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!news-server.csri.toronto.edu!mailrus!cs.utexas.edu!rutgers!ub!oswego!news
From: dl@g.g.oswego.edu (Doug Lea)
Newsgroups: comp.sw.components
Subject: Re: OOP and re-usable cakes
Message-ID: <DL.90Aug5085427@g.g.oswego.edu>
Date: 5 Aug 90 12:50:31 GMT
References: <27705@athertn.Atherton.COM> <71800004@m.cs.uiuc.edu>
 <620@.tetrauk.UUCP> <7057.26b57e9c@swift.cs.tcd.ie> <707@tetrauk.UUCP>
 <382@taumet.com>
Sender: news@oswego.Oswego.EDU (Network News)
Reply-To: dl@g.oswego.edu
Organization: SUNY Oswego
Lines: 120
In-reply-to: steve@taumet.com's message of 4 Aug 90 21:07:56 GMT