The contribution of object oriented programming
to the practice of program develop\-ment lies in the facilities
it offers to specify in a declarative way the structure of a program
as a collection of related objects.
An object oriented program reflects the conceptual structure
of a problem domain by specifying the proper data types,
and their relation by means of inheritance.
Object oriented programming can best be regarded as a methodology,
the essence of which is captured by the directive implied by the phrase
object oriented modeling.
\oopindex{modeling}
Object oriented languages contribute to this methodology by providing the necessary
technology.
In this section, we will study the various mechanisms incorporated
in object oriented programming languages and at the end we will come back to the
more general issues that play a role in requirements analysis
and the design of an object oriented system.\ftn{
See [Sau89] and [BPS89] for an overview and comparison of object oriented
programming languages.
}
A succinct formulation of the basic ingredients of object oriented programming languages
is given by the equation
[M] OOP = encapsulation + inheritance
These mechanisms, encapsulation by means of abstract data types and inheritance,
allow to construct a declarative model of a given problem domain.
When speaking of the declarative nature of object oriented programming,
we do not intend to say that an object oriented program has a logical
interpretation that is as strictly defined as the declarative interpretation of a logic
program, but that in a rather loose sense an object oriented program may reflect part
of the reality that it intends to model.
The objects that we describe in an object oriented specification
may thus partly correspond to entities in reality, although inevitably
there will be objects for which such correspondence is not evident.
These correspondences enhance our conceptual understanding of a program.
\nop{
Evidently, this comes not for free, but is the result of careful design,
that is a discipline rooted in the intention to specify an adequate model of the problem domain.
}
History
\oopindex{history}
Object oriented programming has its root in simulation.
The first language supporting objects was Simula [DaNy66].
Simula has been primarily used to simulate complex dynamic systems.
Since Simula supported co-routining, objects could coexist
in a quasi-concurrent fashion, exchanging messages
in order to direct the flow of control.
The conception of computation as the exchange of messages between objects proved to be fruitful,
as became apparent with the introduction of Smalltalk.
Originally, Smalltalk was intended as a language for programming
interactive graphic work-stations.
This intention has been realized, to the extent that similar languages
are used nowadays to implement
menu-driven, window-based user interfaces.
C.f. [LVC89], [Meyro86].
The introduction of Smalltalk meant both the introduction of a new language
and the introduction of a radically different style of programming.
Along with a new style came a new terminology,
the now familiar terminology of objects, classes, methods,
messages and inheritance.
Data abstraction
\oopindex{data abstraction}
Why has the introduction of object oriented programming resulted in such a
radical change of our conception of programming?
Differently, phrased, what have been the developments that have led
to the acceptance of object oriented programming
as a new paradigm?
These developments may be traced back to the introduction of
structured programming in the 1970s.
The advent of structured programming goes hand in hand
with the dominance of what we may call the procedural style of programming.
Developing a program by means of stepwise refinement was generally taken
to consist of breaking up a problem into a number of abstract steps
or procedures, that were then gradually refined by more detailed procedures.
The effort went primarily into finding a proper algorithm and the procedures
implementing it.
The major disadvantage of the procedural approach was its inadequacy
with respect to the representation of data as structured entities.
The theory of abstract data types offered a correction to these shortcomings
and may be regarded as the most important constituent of object oriented programming,
since it provides a mathematically well-founded notion of encapsulation
as a means to specify the behavior of an entity in an abstract way.
An example of the abstract specification of a data type stack
is given by the algebraic theory below.
\oprog{stack}{
.so stackadt
}
The algebraic specification of a stack has three components:
a signature component that declares the functions needed to
create and manipulate a stack,
a component that specifies the preconditions that must be met
when calling these (partial) functions,
and a component that specifies the semantic constraints
characterizing the behavior of a stack by means of equational axioms.
The preconditions for applying the functions pop
and top state that the stack may not be empty,
otherwise the result of the function will not be defined.
The axioms fully describe the behavior of a stack.
As an example, the composition of a pop
and push operation, with push executed first,
is evidently an identity operation for any conceivable stack.
.so adt
Data hiding
\oopindex{hiding}
An abstract data type specifies the behavior of a category of entities.
Internal details of how such behavior is
implemented remain hidden from the user of such entities.
In this sense, the theory of abstract data types has certainly contributed to
our awareness of the importance of data hiding.
These developments have been taken up by programming language designers
and have resulted in the introduction of modules
and a distinction between specification and implementation parts.
An example of a language supporting such features
is Modula-2 [Wirth83].
The major disadvantage of modules, however,
is that they do not constitute a type and may not be regarded
as first class entities,
however valuable they may be in providing a modularization mechanism.
As argued in [St88] and [Meyer88],
objects may be regarded as implementations of abstract data types,
since they encapsulate data and behavior.
Moreover,
an interface may be specified that hides all internal details of an object
and prevents unprotected access to its data.
Not all object oriented languages, however, provide such a protection mechanism.
Smalltalk [GR83], C++ [St86] and Eiffel [Meyer88] are languages that do provide such support.
Inheritance
\oopindex{inheritance}
As a method of program development, the paradigm of data abstraction
may be characterized as the activity of finding the right data types and specifying
the appropriate behavior for these types.
Abstract data types alone, turn out to be rather inflexible
and inconvenient for specifying large programs in a structured way. C.f. [St88].
Inheritance allows such specifications to be related in the sense that they may be shared
or organized in a specialization hierarchy.
In the view of most, with the exception of [Booch86], inheritance is an
integral part of the object oriented approach.