
[For -Funes (& G&P), The Memorious- (Borges)] fr. Handbook of Programming Languages Volume I (of IV): Object-Oriented Programming, Peter H. Salus, Series Editor in Chief, Macmillan Technical Publishing, 1998, USA. [*][-][-][-]This section by Timothy A. Budd, Oregon State University, [*][-][-][-]

The Cabaret Voltaire! Group Loading Doc [Home]
Back To Lit/Phil
The fundamental concept in understanding object-oriented programming has nothing to do with
programming languages. Instead the key involves thinking about how one goes about structuring
the solutions to problems. This approach can easily be described without reference to program-
ming at all. My book An Introduction to Object-Oriented Programming (Budd, 1997) offers
the following scenario:
Suppose I wish to send some flowers to a friend for her birthday.
She lives in a city many miles away, so my picking the flowers and
carrying them to her door myself is (almost -WedB) out of the question.
Nevertheless, sending her the flowers is an easy enough task; I merely
go down to my local florist (who happens to be named Flo), tell her
the variety or number of flowers I want sent and my friend's address,
and I can be assured the flowers will be delivered expediently and
automatically.
Agents and Messages
All the fundamental features of object oriented programming can be identified in this simple
and common situation. The mechanism used to solve the previous problem involved finding an
appropriate agent (in object-oriented terms, an object) and giving to this agent a -message-
that describes the request. In this scenario, the agent is the florist Flo, and the message is the
selection of flowers desired and the addresses of the person to which the flowers should be
sent. The sender does not know - nor does he need or want to know - the exact details
concerning how the request will be carried out. Of course, the florist might well deliver
a slightly different message to another florist in another city, who has earlier communicated
with a flower wholesaler, and who now must communicate with a delivery person, and so on.
Thus as entire community of individuals must cooperate with each other to satisfy my request.
If we rephrase this approach to problem solving in more technical terms, it produces a situ-
ation that applies to object-oriented programming. In this case, action is initiated by the
transmission of a message to an agent (an object) that is responsible for the action. The
message encodes the request for an action and is accompanied by any additional information
(arguments) needed to carry out the request. The receiver is the agent to whom the message
is sent. If the -receiver- accepts the message, it accepts the responsibility to carry out the
indicated action. In response to a message, the receiver performs some method to satisfy
the request.
There is an ironic twist to viewing programming in these client/server terms. People are gen-
erally accustomed to depending on others for the advancement of their own goals. It is very
much human nature that when a person is faced with a new problem to solve, one of the first
questions he asks himself is who he can call on to help him with the problem at hand. Program-
mers, on the other hand, tend to be a fiercely independent lot. They most often are mistrustful
of any code they did not themselves have a hand in creating. Thus, although the object-oriented
perspective of structuring a problem as a cooperating community of interacting agents might seem
natural to novices, long-time expert programmers sometimes have a much more difficult time.
Programmers must consciously work to resist the temptation to write everything from scratch and
must be continually encouraged to make use of existing components and existing solutions to
common problems.
Responsibilities and Information Hiding
In considering the scenario describing my interaction with the local florist, an important fea-
ture to note is that the florist is described by the services she provides, not by the actions she
takes in the performance of her duties. In computer terms, this is called information hiding. I
don't really know how my request will be processed, I don't really care to know. All I know is
that my florist has agreed to the responsibility for providing this service, and that, having
accepted my message, the florist will take the necessary actions.
The link between message and action in both the real world and in the object-oriented world is
less binding than, for example, the link between a function name and a function implementation
in a conventional programming language. This is because a message is transmitted to a receiver,
and the interpretation of the message (that is, the actions to be performed) is determined entirely
by the receiver. As a result, different objects might understand the same messages but might react
differently. For example, an executive can give the same message to his/her secretary that he/she
gave to the florist (namely, the address of the friend, the type of flowers desired, and the credit
card number for payment) and will expect that the dsired outcome will be achieved. But the
actions that the secretary performs might be very different from those of the local florist.
Thus the same message can elicit two entirely different behaviors.
Thus, the idea of messages in object-oriented programming is intimately tied to the concept of
information hiding. The difference between viewing software in traditional, structured terms
and viewing it from an object-oriented perspective can be summarized by a twist on a well-
known quote:
Ask not what you can do to your data structures, but rather ask
what your data structures can do for you.
Classes and Instances
Although I have dealt with Flo the florist only a few times, I have a rough idea of the behavior I
can expect when I go into her shop and present her with my request. I am able to make certain
assumptions because I have some information about florists in general, and I expect that Flo,
being an instance of this category, will fit the general pattern. We can use Florist to represent
the category (or class) of all florists. Let us incorporate these notions into our next principle
of object-oriented programming:
All objects are instances of a class. The method invoked by an object
in response to a message is determined by the class of the receiver. All
objects of a given class use the same method in response to similar messages.
The same idea is incorporated in object-oriented programming languages. In a painting applica-
tion, for example, I might have several instances of a general class Rectangle being displayed
in a window. Each rectangle is in a sense different; each might have a color or shape, for
example. Yet each is also similar to the others; each could be, for example, moved or resized
using the same commands. The notion of a class lets me describe the common features of the con-
cept, while still allowing each object to have some sense of individuality.
Inheritance
I have more information about Flo -- not necessarily because she is a florist, but because she is a
shopkeeper. I know, for example that I probably will be asked for money as part of the trans-
action, and that in return for payment I will be given a receipt. These actions are true of grocers,
stationers, and other shopkeepers. Because the category Florist is a more specialized form
of the category Shopkeepers, any knowledge I have of Shopkeepers is also true of
Florists and hence of Flo.
The principle that knowledge of a more general category is also applicable to a more specific
category is called inheritance. We say that the class Florist inherits attributes of the class
(or category) Shopkeeper.
Classes can be organized into a hierarchical inheritance structure. A child class (or subclass)
inherits attributes from a parent class higher in the tree. An abstract parent class is a class
(such as Mammal) for which there are no direct instances; it is used only to create subclasses.
In programming languages, inheritance applies both to data values and to functions (that is,
behavior). Both data fields and functions associated with a parent class become associated
with child classes and are available for use when instances of a child class are created.
Method Binding and Overriding
The concept of an inheritance hierarchy is the key to understanding not only how separate
concepts can share common features, but also how ideas can override, or hide, their inherited
attributes.
The search for a method to invoke in response to a given message begins with the class of the
receiver. If no appropriate method is found, the search is conducted in the parent class of
this class. The search continues up the parent class chain until either a method is found or the
parent class chain is exhausted. In the former case, the method is executed; in the latter case,
an error message is issued. If methods with the same name can be found higher in the class hier-
archy; the method executed is said to override the inherited behavior.
Overriding occurs in everyday life as well as in the object-oriented world. We know that mam-
mals, for example, give birth to live young. Yet the catagory Platypus inherits from class
Mammal, and platypuses lay eggs. In our model of the universe, the concept of giving birth
to live young is associated at the Mammal level of Figure 1.1, while the concept of laying
eggs at level Platypus overrides the inherited behavior. When we search for information
concerning the breeding habits of a specific animal, we search the most specific category
before progressing to the more general.
[Illustration (Figure 1.1) Here]
Polymorphism
In a sense, it doesn't really matter whether I give my message to my florist directly, or to my
secretary, as long as the resulting actions are satisfactory. Objects can be characterized by
their behavior, and as long as the behavior is acceptable for certain problems, the particular
characteristics of the object should be unimportant. In object-oriented languages, the inheri-
tance heirarchy often is used not only for sharing code but also for describing characteristics.
[It has been noted that these two goals are not always coincident, and should not necessarily be
handled by the same mechanism. This brief overview does not permit me to discuss the subclass/
subtype distinction, or introduce some of the techniques used to separate these concepts.
Interested readers should consult my book An Introduction to Object-Oriented Programming,
2nd Ed.] For example, the class Mammal can be viewed as both a convenient handle (or storage
container) for holding our general information about Mammals, and, as well, a defining constraint.
If I tell you, for example, that a certain animal is a Mammal, you immediately know a lot of
information about it.
In programming languages this simple idea becomes manifest in the notion that we can separate
the declared type of a variable from the value that it holds at any particular time. Imagine that
we have a class hierarchy that mirrors that shown in Figure 1.1. We might have a variable that
is declared as Mammal. In fact, it could be holding a value that is of type Dog. Since a Dog
is aMammal (by which we mean that the category Dog inherits from the category Mammal),
any behavior that we expect from the more general class should certainly be exhibited by an
instance of the child class.
The term polymorphism is often used to describe this idea. Polymorphism means roughly
"many forms"; the variable that is declared as Mammal can, during the course of execution,
take on many different forms -- perhaps holding at one instance a cat, and another time a dog,
at still another instance a human being.
This is an extremely simple idea with many powerful and subtle implications. It is the feature
that permits the development of software frameworks, for example. A framework is a
skeleton application that provides the structure, but no specific information, for solutions
to a set of similar problems. The most common type of framework is a graphical user interface
framework, or GUI. A GUI can be written so that it deals with a general class Window, for
example (see Figure 1.2). A window has general characteristics, such as a rectangular shape,
a height and width, the ability to be resized, moved around on the display surface, hidden,
restored, made into an icon, and so on.
[Illustration (Figure 1.2) Here]
All these general characteristics can be defined without reference to the particular contents
of the window, in just the same way that we can discuss the characteristics of mammals without
reference to a particular type of animal. The programmer using a framework then develops a
new type of window by creating a subclass from the class Window (for example,
GraphicsWindow). Features that are particular to to the new application, such as the display
of the contents of the window, are defined in this new class. Because the framework holds the
window value in a polymorphic variable, the framework thinks the window is an instance
of the class Window, whereas the programmer knows the actual value is an instance
of the class GraphicsWindow.
Object-Oriented Computer Programming
Although object-oriented techniques may be easy to apply in real life, they can be frustrat-
ingly difficult to discover in computer programs. In real life the boundaries between objects
are obvious and clear-cut. People are different from and interact with each other, balls
bounce, birds fly, trees grow. The interface between physical objects are sharp and deifinable.
When pondering the interaction between a baseball and the bat that hits it, we do not ask
which object has the responsibility for determining that a collision has taken place or which
object should control the change of state that occurs when they interact.
But such decisions are the heart and soul of object-oriented design. In this respect, the
process of object-oriented design is closer to the smooth functioning of an organization,
such as a committee or club. Here the separation of responsibilities between, for example,
the president and the vice-president may not be so clear-cut as the separartion of responsi-
bilities between a ball and a bat. Tracing the flow of interactions so that all necessary
tasks are performed, all contingencies are predicted, and no one person (or object) is
overburdened by too much work can be frustratingly difficult both in real life and in object-
oriented programming.
Much of the recent work in object-oriented design, such as the unified modeling, as well as
work in object-oriented structuring, such as the design patterns movement, can be seen as an
attempt to provide guidelines that help determine how to divide responsibilities between many
agents.
Summary of Object-Oriented Concepts
Alan Kay, considered by many to be the father of object-oriented programming, identified the
following characteristics as fundamental to OOP (Kay, 1993):
* Everything is an object.
* Computation is performed by objects communicating with each other, requesting
that other objects perform actions. Objects communicate by sending and receiving
messages. A message is a request for action bundled with whatever arguments
may be necessary to complete the task.
* Each object has its own memory, which consists of other objects.
* Every object is an instance of a class. A class simply represents a grouping
of similar objects, such as integers or lists.
* The class is the repository for behavior associated with an object. That is,
all objects that are instances of the same class can perform the same actions.
* Classes are organized into a singly rooted tree structure called the inheritance
heirarchy. Memory and behavior associated with instances of a class are
automatically available to any class associated with a descendant [of that class -WedB]
in this tree structure.
OOP: An Evolutionary Idea
Having tried to convince the reader that object-oriented programming is a revolutionary idea,
totally unlike anything that has come before, I will now endeavor to show that it is really
evolutionary, clearly following on the heels of a long tradition of previous abstraction tech-
niques. From the beginnings of computer science it has been clear that the major difficulty
in the development of large systems is not algorithmic, but is, rather, communication. Fred
Brooks, in 1975, expressed it this way:
Since software construction is inherently a systems effort -- an exercise in
complex relationships -- communication effort is great, and it quickly dominates
the decrease in individual task time brought about by partitioning. Adding more
men then lengthens, not shortens, the schedule. (Brooks, 1975)
Over the years, programmers and language designers have developed a number of abstraction
techniques to help control the flow of information between various parts of a large software
system, as well as between the various members of a software delvelopment team. Symbolic
assembly languages, for example, enabled the programmer to think about operations by name,
rather than by numerical address. High-level languages freed the programmer from tasks such as
register allocation and management. Procedures separated the naming of a task to be performed
from the steps used in the achievement of the task, and started the long progression of infor-
mation hiding mechanisms. Procedures by themselves cannot be used to hide information that
must be shared between two or more routines. Block-scoped languages, such as Algol, were
one attempt to solve this problem; modules were a slightly later and more successful
mechanism.
David Parnas (1972), who popularized the notion of modules, described the following two prin-
ciples for their proper use:
* One must provide the intended user with all the information needed to use a module correctly,
and nothing more.
* One must provide the implementor with all the information needed to complete a module, and
nothing more.
This philosophy is much like the military doctrine of "need to know," and should be etched on
the inside of the eyelids of every good object-oriented programmer. When objects interact with
each other, they should be tied together with the weakest strings possible.