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.