\section{Background}

A usable approach to software engineering must cover the
entire software life cycle from requirements analysis through
design, implementation, maintenance, and extension. As
with older approaches to software construction,
object-oriented methods may be applied in all phases of
software work. As often stated, one role of a
programming language in object-oriented methodology is as
a tool for carrying out the
implementation phase. Of course, the closer the language
is to reflecting concepts of the methodology, the easier
it will be to implement a design.

The most fundamental concept in object-oriented
software methodology seems to be its focus on data objects and their
encapsulation together with the sets of operations to be used
in connection with the role of the objects in the application
program. This notion of {\em data abstraction} is in contrast
to the emphasis on process and procedure in other software
engineering approaches that appear to lack a structured way
of dealing with data objects.

Although the concepts of abstract data types, which provide a
precise formal foundation for the encapsulation of object classes,
is a well-understood area in sequential programming
languages~\cite{Liskov77},
there is no agreement about how the abstraction should be carried
over to parallel and distributed systems. The most common approach
is simply to allow independent processes to have free use of access
and update operations on arbitrary objects. This leads to the
possibility of nondeterminate behavior of computations, whether or
not repeatable behavior is desired by the programmer. Our view is
that this is an unacceptable approach. Programmers should not
have to expose themselves to unrepeatable behavior when that is
not a requirement of the application!

There is nothing in the rationale for object-oriented software
methodology, as stated by Blooch~\cite{Blooch94} and by
Rumbaugh~\cite{RumbaughEtAl91}, that demands that objects have {\em mutable
state}. Thus a real-world object that progresses through a significant
sequence of states may be modeled by a {\em sequence} of state values,
together with static data that describes fixed attributes of the
object. Stream data types provide this capability, and our examples
show how this approach may be practiced using ObjectSisal. 

{\em Inheritance} is another aspect of object-oriented methodology that is
held to be characteristic of the field. There seem to be two
principal sorts of inheritance: The first corresponds to a
subtype hierarchy generated by the ``is-a'' relation among object
types. This form of inheritance may be added to a functional
programming language by a simple extension of the syntax for
defining abstract data types, as we illustrate in
Section~\ref{principles} for the Sisal language. The second
object-oriented use of inheritance concerns aggregates, the
``part-of'' hierarchy. This concept can be
applied simply by nesting (binding) type definitions as required by
the structural relationships of data objects.

The motivation for
inheritance appears to be the savings in program text and compiled
code for operations that have similar effects for several
specializations of a superclass of objects. This appears to
be a valid argument where the operation does not apply to all
subtypes of objects; when an operation applies to all subtypes
(even if there are different effects for differing types of objects),
it seems to be more efficient to apply the operation to the
common superclass and use case analysis to determine the
effect according to kind of object as given by an attribute of the
superclass. These aspects of hierarchy will be illustrated in
the examples of the next section. 

We do not consider the topic of {\em multiple inheritance} because
its semantics and utility are being questioned, even within the
community of conventional objected-oriented advocates. 

