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.