Object-oriented programming
Introduction
In the past couple of years, object-oriented programming has become a
buzzword roughly equivalent to ``good.'' In this section, we give a
more realistic presentation of object-oriented methods, and what they
stand for.
Object-oriented programming was invented to solve certain problems of
modularity and reusability that occur when traditional programming
languages such as C are used to write applications. This fact makes
it hard for a non-experiences programmer to appreciate object-oriented
techniques.
To avoid being influenced by specific programming languages and their
particularities, we start by giving a very general presentation of the
ideas behind object-oriented programming. We then discuss how these
general techniques map to specific programming languages such as Java
or CLOS (the Common Lisp Object System).
General terminology
Object
An object defined to be a value that can be assigned to
variables, supplied as arguments to functions, and returned as values
of function calls. An object has an identity so that two
values can be compared to test whether they are in fact the
identical object. If uniform reference
semantics is used, then assignment of objects preserve this
identity. Usually, but not always, an object is implemented as a
pointer to a block of memory that is allocated for the object when the
object is created. But simple objects such as integers and
floating-point numbers may not have any allocated memory associated
with them. Instead, they are fully contained in the value itself.
Identity and uniform reference semantics can still be preserved,
provided that no side effects are possible to such objects.
Abstract data type
An abstract data type (or type, for short) is a set
of objects. Types are not necessarily mutually exclusive, so that an
object can be of several types. In particular, a type can be a subset
of another type, so that all objects of type automobile
are also objects of type vehicle.
Operation
An operation is a function or a procedure whose arguments are
objects. Each possible argument is of a certain type. For instance,
mount-engine might be an operation that takes two
arguments, an object of type motor-vehicle and an object
of type engine, and has the side effect of altering the
engine of the motor vehicle. Similarly, push might be an
operation that takes two arguments, an object of type
stack and an object of arbitrary type, and has the side
effect of inserting the second argument on the top of the stack.
Protocol
A protocol is a collection of operations that are usually
needed simultaneously. Typically, at least one type is common
between all the operations in the protocol. An example of a protocol
would be drawing graphics objects. Such a protocol would
contain operations such as draw, erase, and
move using objects of type window,
pixmap, circle, rectangle,
etc.
Class
A class describes the implementation details of a collection
of objects, such as the number and names of the fields (or slots). A
type is typically made up of a collection of classes that may
or may not be related by inheritance.
An object is said to be a direct instance of exactly one
class, and that class is called the class of the object.
Inheritance
Classes are organized in a hierarchy that can be a directed acyclic
graph (multiple inheritance) or a tree (single inheritance). An
object is the instance of a class C if and only if it is
either a direct instance of C, or an instance of a class
that inherits from C (or, equivalently, is derived
from C).
If a type contains the class C, then it also contains all classes
derived from C.
Object-oriented programming in CLOS
Method
A method in CLOS is a partial implementation of an operation. It is
partial, in the sense that it implements the operation for a
particular set of classes of the arguments. For the operation to be
completely implemented, methods are needed that cover all possible
classes that make up all possible types possible of the arguments.
The methods that make up the implementation of an operation can be
physically distributed. They are recognized as belonging together
because they have the same name.
Generic functions
A generic function is the complete implementation of an
operation. It is used as an ordinary function. A particular partial
implementation, a method, is chosen according to the classes of the
arguments.
Generic dispatch
The mechanism that selects a method of a generic function according to
the classes of the arguments is called generic dispatch.
CLOS has multiple dispatch, which means that the generic
dispatch mechanism can take into account several arguments in
order to decide which method to use.
Multiple inheritance
CLOS supports multiple inheritance, which means that a class can
inherit from several parent classes.
Object-oriented programming in Java and other languages
In Java, C++, Smalltalk, Eiffel, Simula, and other object-oriented
languages, things work differently from CLOS.
Static typing
Some of these languages are statically typed, which means
that the user has to declare what kind of objects can be the value of
a particular variable or parameters. Roughly speaking, the declared
type of a such variables or parameters must be the name of a class.
As a consequence, an abstract data type must also be a
class. This is accomplished by always creating a class
(potentially without any instances), from which all other classes that
make up the type are derived. The name of the root class of such a
hierarchy is usually the same as the name of the type.
Restrictions on operations
All of these languages use only single dispatch which means
that a partial implementation of an operation can be selected based on
only one (the first) argument. In fact, all of these languages
threat the first argument so differently that there is a special
syntax for it. Whereas in CLOS, one would say:
(mount-engine *my-car* *the-engine*)
In these languages, one would say something like:
my_car.mount_engine(the_engine)
if dispatch is wanted on the type of car, and
my_engine.mount_engine(my_car)
if dispatch is wanted on the type of engine.
That special syntax makes it impossible to pass a generic function
(here mount_engine) as an argument to another
function.
Since methods are so closely related to one particular class, in these
languages methods are in fact physically written inside the
declaration of the class itself, further cementing this relationship.
Single or multiple inheritance
Some of these languages support only single inheritance, such as
Smalltalk. C++ supports multiple inheritance. Java, although
supporting only single inheritance, has a feature called
interfaces which makes it possible to obtain most of the
features of multiple inheritance.