Object Orientation


This page is primarily for folks with no prior experience or training in object-oriented disciplines. "Prior experience or training" usually means experience or training in object-oriented programming, but might come from fields like cognitive psychology or artificial intelligence. These and many other fields have been influenced by, or have contributed to, the set of ideas called object orientation.

Object orientation is one of the half dozen or so big, crucially important concepts to come out of the last few decades of computer and information technology. There are a few basic principles behind all object-oriented disciplines, with a broad range of applicability to fields such as programming, user interface design, and computer systems architectures.

The key idea in any discussion of object-orientation is the notion of an object. This is a familiar word; take a moment and think about what it means in ordinary language. Some aspects of objects in the technical sense may at first appear strange, but analyzing how people perceive and think about objects will help to resolve the apparent problems. The object-oriented paradigm is most mature in the field of programming languages, but it was not primarily motivated by considerations of computer science. Its roots lie in efforts to make computers more comprehensible to people.

Take a look at the characteristics of an object in the world as we might perceive it:

  • It is closed or encapsulated; that is, it is a "thing in itself," separate from other things, revealing itself by its external behavior (which includes tangible properties such as color, size, texture, as well as motion, sound, etc.). The internal structure of the object is accessible only if it is "cut open" in some way.

  • An object may be composed of other objects, which determine how it behaves. For example, a car is composed of body, engine, suspension, etc.; and these in turn are also composed of simpler objects.

  • Although each object is unique, it is usually similar enough to certain other objects that we can put them into the same category or class. The quarter (25 cent coin) I have in my pocket is unique, but I can think of it as differing from other quarters only by a few parameters such as date, location, etc. This particular quarter can be considered an instance of its class. Another way of looking at it is to say that we could clone one instance from another, with minor differences.

  • Different classes of objects often have enough in common that we would like to lump them together. Quarters and pennies are different, but they are both coins. Technically, the class of pennies and the class of quarters are both subclasses of the class of coins, or the class of coins is a superclass of the classes of pennies and quarters. This general idea has existed at least since Aristotle. Think of the biological classification scheme: Horses are mammals, mammals are animals, animals are living things, etc. It economizes resources in perceiving and thinking; as soon as we fit a horse into the category (or class) mammal, we know that it is warm-blooded, because horses derive or "inherit" that characteristic from mammal.

Two other aspects of objects are important. They stem from the relation between an object and its name:

  • Proper names of objects do not usually specify what kind of object they refer to. For instance, I might have a son named "Joe", or a father, a pet dog, etc.

  • If I take some action on "Joe", for example saying "Joe, go to bed", the results will depend very much on what sort of object Joe is. (My son might go to bed, my father would probably object, my dog might give me a puzzled look.)

Now consider some examples of what "objects" might be in the technical sense of object-oriented programming, object-oriented database, etc. Software modules, "things" that a programmer builds to provide some externally visible behavior or function, can be objects. In object-oriented programming (OOP), these modules encapsulate both programs and the data that makes an individual object unique. Things stored in OO databases are also objects. Without going into the technical details, these are not just passive data. They are more like the objects of OOP, except that they are persistent; they do not go away when the program ends. Things that users interact with in an interface to a computer system (folders, documents, etc.) can be objects, and can be external representations corresponding to OOP constructs.

The general principles of object-orientation can be summarized as follows, based on the object properties discussed above:

  • Encapsulation: Objects reveal their "outside" through tangible behavior, but keep their "inside" hidden. Another way of saying this is that we do not need to know how an object works to know how it behaves.

  • Composition: The behavior of an object may result from the collective behavior of objects from which it is composed or constructed.

  • Classes: Groups of objects can share common characteristics or can be cloned from a common prototype. Objects are said to be instances of their classes.

  • Inheritance: The behavior of a superclass can be "handed down" to (or inherited by) its subclasses.

  • Polymorphism: Object behavior in response to the same action or message may take many forms, depending on the class of the object.

Object-Oriented Programming

The term "object-oriented" is most often seen in "object-oriented programming," or "OOP". Assuming you have programmed in some language such as COBOL, FORTRAN, or BASIC, here is a quick tour of how the general principles of object-orientation apply to programming.

Encapsulation: The behavior of a program depends on both algorithms and data structures. In many programming languages, algorithms are coded into program modules (usually called procedures or functions), and data structures are represented separately. When a function is called, the programmer must pass the data structure it will operate on. An object-oriented program module - usually called simply "an object" - encapsulates both algorithms (code) and data. Other objects communicate with it by calling it or sending messages, and never see its internal structure. There is a function, or method, that gets executed for every message. Each object has instance variables that hold its unique, private data. Typically, these "objects" represent things in the real world. As an example, consider the object "my savings account" (in a bank). In real life I might want to deposit money into it, query the balance, withdraw, etc. So a programming object, mySavingsAccount, in a banking application might respond to the calls deposit(amount), queryBalance, withdraw(amount), etc. mySavingsAccount probably has an instance variable called balance, and others for account number, customer name, and so forth. Proponents of OOP believe that this kind of design for an application is easier to understand, and thus easier to implement and maintain. Software engineers will recognize this sort of thing as "information hiding," "separation of concerns," etc. The difference from classical software engineering or "structured" approaches, however, is that the problem has been decomposed into objects rather than functions.

Composition: Expanding on the banking example, imagine an application for a full-service institution. It might provide FinancialPortfolio objects that contain, or are composed from, BankAccount, Stock, Bond, InsurancePolicy, etc., objects. (In a fully object-oriented system, an application is itself an object composed of other objects.)

Classes: In the bank example, do we want to code each SavingsAccount object individually? After all, they differ only by a few parameters (account holder name, balance, etc.). Classes in an OOP system are templates or prototypes from which programs can create new objects. mySavingsAccount, for example, is an instance of the class SavingsAccount. Typically it would be created by sending a message to the class telling it to create a new object. The message would include arguments or parameters to initialize the object’s instance variables, in this case the customer name and balance:

mySavingsAccount =
       SavingsAccount new('Dave Collins', 1500.00)

The ability to support classes is one of the differences between OOP languages, such as Smalltalk, C++, and Java, and "conventional" languages such as Pascal, PL/I, and C. Technically, the class holds the programming code for the object’s methods. The object itself holds its data (which is unique) but points to the class for methods (which all instances of the class share).

Inheritance: Think about implementing a class called CheckingAccount. Clearly it has a lot in common with SavingsAccount; why not factor out the common behavior into a superclass BankAccount? There is a cognitive economy in thinking of savings accounts and checking accounts as special kinds of bank accounts; OOP systems mirror this by providing mechanisms to code the SavingsAccount and CheckingAccount classes not from scratch, but by specifying how they differ from a BankAccount superclass. The code in BankAccount defines all the common characteristics of savings and checking accounts. This results in code reuse and conceptual clarity. The example just given might be coded as

BankAccount subclass: SavingsAccount.

The figure below is a "doughnut diagram" showing an object of class SavingsAccount receiving the message withdraw(50.00).

Doughnut diagram of an object, methods in a ring around the object's data

The message will be processed by the withdraw() method (or member function). The center of the doughnut holds instance variables. Methods are around the outside, surrounding the instance data; this shows graphically that instance data is private, and can be accessed only by the object’s methods.

This figure is a common way of representing the inheritance relationship between different kinds of bank accounts:

Hierarchy diagram of bank account classes

Suppose, in this situation, we wanted a class representing "negotiable order of withdrawal" (NOW) accounts. NOW accounts are similar in some ways to both savings and checking accounts. Could we inherit from SavingsAccount and CheckingAccount to form the NOWAccount class? Some languages (such as C++) allow multiple inheritance, and for them the answer is yes. Others (such as Smalltalk and Java) allow only single inheritance, and the answer is no.

Dynamic binding: Two other significant aspects of objects were mentioned, related to naming them. When we declare the name of a variable in a conventional programming language, we usually specify what type of object it refers to (for example, a real number, an integer, a character string, etc.). This can be a problem in object-oriented languages. Suppose I want to process all the accounts for a given bank in some way that does not depend on whether an account is savings or checking. It seems natural to declare a variable to be simply a BankAccount, and let it actually (when the program is running) be either a SavingsAccount or a CheckingAccount. In the terminology of programming languages, functions to be invoked by messages to the object referenced by the variable are dynamically bound at the time the program is run. (As opposed to being statically bound at the time the program is compiled.) If we do not know the type of an object, how can we (or the language compiler) figure out which method to execute when the object receives a message? In object-oriented languages, the answer is simple. Since operations are "packaged" into the object itself, it just does whatever is appropriate. Though this may sound strange to a programmer, notice that it is exactly how objects in the real world behave. Since object behavior in response to an action may take many forms, depending on the object, this is called polymorphism, from a Greek word meaning "many forms". Polymorphism makes OOPLs very flexible. New kinds of objects can be added without changing existing code, as long as they respond to the same messages. For example, imagine adding a MoneyMarketAccount class in the banking example. If MoneyMarketAccount objects respond to deposit, withdraw, etc., they can easily be added to existing applications.

For specific examples of OO programming languages, see our pages on Smalltalk, C++, and Java.