Nearly everyone has heard that Object Oriented Programming (OOP) is coming soon to a computer near you. In fact, OOP has been around for some time, although it hasn't always had that name. Recent years have seen tools and languages geared at simplifying OOP, and that has created the hype. What does OOP mean to you, as a professional programmer?
If you are already a programmer, you'll probably find many OOP ideas familiar-they just have funny names. If you are willing to learn the meanings of sixteen new (or almost new) words and phrases, you'll have a good command of OOP principles. Most, if not all, OOP languages use the same ideas. If you plan to use C++, Smalltalk, Simula, or LOOPS, you'll still find these sixteen words will help you get a handle on designing and writing OOP code.
Not surprisingly, the first word I want to talk about is object. Non-OOP programs focus on functions, procedures, or subroutines. OOP programs build around objects. Objects are similar to data structures (or Pascal records). The chief difference is that objects contain both data and subroutines (or functions, if you prefer). For example, a string object will contain the contents of the string it represents. It also might contain code to shift the string to upper case. Often, the variables and functions in an object are called members of the object.

How do you actually get a string object to shift itself to upper case? You send the object a message. How you do this depends on the language you are using. Sending a message is often similar to a function call in conventional languages. Messages can return values (or objects) and can take values (or objects) as arguments. For example, your string object might handle several messages:
ToUpper (no arguments-shifts string to upper case)
Length (no arguments-returns length of string)
Concatenate: s1 (one argument-concatenates s1 to string)
PrintOn: d1 (one argument-prints string on device d1)

Selector is a fancy word for message name. For example, in the PrintOn: message above, PrintOn: is the message selector. The argument is d1. When you send a message to an object, that object is sometimes called the receiver.
How does your string object know what to do when it gets a ToUpper message? It uses a method. A method is a subroutine that does the work needed to answer (or perform) the message. An object has one method for each message it can accept. (NOTE: That isn't true, but it is good enough for now. You will learn more about handling messages soon.)
An object encapsulates a concept. The string object, for example, encapsulates all data and subroutines that concern strings. Perhaps when you wrote the string object, you decided to store the strings in an array. Later, if you decide to store them using linked lists, you need only change the string object. If you support the same messages (and they don't change meanings) your program will still work. This is simply modular programming carried to an extreme.
It would be very bad if you had to write a string object, complete with all the necessary methods, for each string in your program. Instead, OOP languages allow you to define classes. You don't write a string object, you write a string class. This class is a blueprint for all string objects. While you might have 100 string objects in a program, there will always be exactly one string class. You can send a class messages, just like it was an object. Every class knows one message, usually called New. This message tells the class to make a new object.
As an example, consider a class, SerialRcvr. This class knows how to read characters from a serial I/O port. However, the class doesn't actually communicate with the port. It is only a blueprint for objects that will. If the system has two serial ports (0 and 1), you might write:
| Com1:=SerialRcvr<-New: 0; | |
| Com2:=SerialRcvr<-New: 1; |
in a hypothetical OOP language. This would send the message New to the SerialRcvr class with an argument specifying which port to use.

In the above example, Com1, and Com2 are instances of the SerialRcvr class. Objects are always instances of a class. Creating a new class is often called instantiating an object.
Each object (or instance) has its own variables, as defined in the class. For example, each instance of SerialRcvr (Com1 and Com2) have their own data buffers, and their own methods to respond to messages. Many OOP languages only allow an object's methods to access its instance variables. Others allow you to specify that some variables are accessible outside the object-this is usually not a good idea since it destroys encapsulation.
Each class has a list of instance methods that apply to objects of that class. These methods handle messages directed at any instance of the class, but not at the class itself. However, it is important to notice that the class keeps one copy of the instance methods that all instances use.
Classes can have their own variables. SerialRcvr, for instance, might keep a running count of errors that occur on any serial port. These variables are accessible to all instances of the class, and may be used as semi-global variables. For example, all instances of SerialRcvr would increment the error count when they detected an error. Like instance variables, class variables are usually only accessible by instances of the class (or the class itself).
Since classes can respond to messages, they must have their own methods. SerialRcvr might have a TotalError method to return the error count accumulated. Often you will write classes with no class variables or methods.
Wait! I just said you will often write classes with no class methods. But
earlier I said that all classes know about a New (or similarly named) method.
How is this possible? OOP languages create classes in a tree or hierarchy. In
many OOP languages there is one class at the top of this class hierarchy. In
other languages, you may have many independent trees of classes.

When an object or class receives a message, it searches through its methods. If it has a method that matches the message selector, it executes that method. If it does not find a matching method, it passes the message up the tree to its parent class. This process repeats until somebody processes the message. If the message makes it to the top of the tree without being processed, an error occurs. (In some languages, the top of the object tree is implicit and not visible to the programmer. Rest assured it is there.) One class can elect to process a message and, as part of that processing, send the message up to its parent class (sometimes called its superclass).
Because of the class hierarchy, you could write a class with only one instance method that handles 100 messages. The other 99 methods would come from the parent classes. These methods are inherited. A class can define a method that its parent does. The new method overrides the parent's definition for that message. Classes also can new messages that only apply to it.
This is a very powerful concept. For example, if SerialRcvr's parent class is Queue, it inherits Queue's methods. It could reuse the methods to retrieve characters from the queue, for example. The class might redefine the methods that place characters on the queue, and add new methods for handling serial protocols.
Some OOP languages allow classes to inherit from multiple classes. For
example, a new class, Terminal, might have both SerialRcvr and SerialXmit as
parents. The language defines what happens if both parents implement the same
method. This technique is known as multiple inheritance.
Design by difference is the reuse of a class to build a new class. You need only implement the portion of the new class that is different from its parents.
Sometimes it is useful to `define a class that only serves as a parent for other classes. Such a class is an abstract class (sometimes called a metaclass). Usually an abstract class requires one or more methods that it doesn't implement. These methods must be implemented by its subclasses. Some OOP languages don't enforce abstract classes-you can instantiate them, even if they are useless. Other languages allow you to write abstract classes that can't create objects.
Consider a graphics program. You could create a class, Shape, that encapsulated all common information about shapes on the screen. For example, Shape might contain the shape's color, and coordinates. However, Shape doesn't know what to draw on the screen. Shape is an abstract class, it does nothing by itself. You could create subclasses of Shape: Circle, Square, Rect, for example. Each subclass would implement the Draw method to place the corresponding shape on the screen.
Assume that you have a variable that is a pointer to a Shape object. The variable also can point to objects that are subclasses of Shape (say a Circle object). When your program sends a Draw message to the object pointed to by the variable, the OOP language must determine that the object is a Circle and call the correct method. This property is polymorphism.
Many, but not all, OOP languages don't even have typed variables. In these languages, a variable is just a container that can hold objects. The OOP language always determines which method to call at run time.
When the OOP language decides what method to call at run time, it performs late (or dynamic) binding. Almost all OOP languages allow late binding. Many OOP languages only support late binding. Since the program must search for methods before each call, there may be some performance degradation associated with late binding.
Some OOP languages can sometimes decide which methods it should call at compile time. It can then generate the correct call at compile time, and avoid the performance penalties inherent in late binding. This process is called early (or static) binding. Early binding is most common in OOP languages with typed variables. However, most OOP languages that allow early binding also allow you specify late binding.
That wasn't so bad. You should review the words until you can define them yourself. When you feel comfortable, you might want to look at some OOP design examples, below.
The following sections contain an overview of several actual object designs for you to examine. For the sake of clarity, the examples only include key variables and methods.
These classes are useful for doing physical I/O to hardware addresses. The parent class, IOCLASS, is a metaclass-it isn't useful by itself. Its children, DIGITAL_IN, DIGITAL_OUT, BYTE_IN, and BYTE_OUT do the work. In a language with multiple inheritance, you could define a child of DIGITAL_IN and DIGITAL_OUT to represent an I/O port. Oddly, such a class would contain no variables or methods. The two parents supply all the methods and variables needed.
When the program instantiates its first object of type IOCLASS (or a subclass of IOCLASS), the NXTPORT pointer is set to NULL (or NIL) in the object. Then, the creation method (usually NEW) sets IOPORTS to point to the new object. When the program creates more objects, their NXTPORT member is set to the value of IOPORTS. Then the value of IOPORTS changes to point to the new object. In this way, IOPORTS points to a linked list of I/O ports. Since you only want one pointer to the start of the linked list, IOPORTS is a class variable. The FINDPORT method searches this linked list for a given name. When if finds a port that matches the name, it returns a pointer to the object. Of course, you will have to augment or replace the default NEW method to set up this linked list.
| PORTNAME | INSTANCE VARIABLE | Contains name of port |
| IOPORTS | CLASS VARIABLE | HEAD of IOCLASS link list |
| NXTPORT | INSTANCE VARIABLE | Pointer to next I/O port |
| FINDPORT | CLASS METHOD | Finds I/O port by name |
| GETNAME | INSTANCE METHOD | Returns port's name |
| PORT | INSTANCE VARIABLE | Port's physical address |
NAME TYPE DESCRIPTION
READBIT INSTANCE METHOD Read 1 bit
| NAME | TYPE | DESCRIPTION |
| WRITEBIT | INSTANCE METHOD | Write 1 bit |
DIGITAL_IO (child of DIGITAL_IN and DIGITAL_OUT)
*****NO VARIABLES OR METHODS FOR THIS CLASS*****
NAME TYPE DESCRIPTION
READBYTE INSTANCE METHOD Read 1 byte
NAME TYPE DESCRIPTION
WRITEBYTE INSTANCE METHOD Write 1 byte
BYTE_IO (child of BYTE_IN and BYTE_OUT)
*****NO VARIABLES OR METHODS FOR THIS CLASS*****
A realistic terminal I/O class could be quite complex. However, the examples below capture the essence of a simple terminal class. This scheme uses two base classes, KEYBOARD and SCREEN. The CONSOLE class is their child. Notice the benefits of encapsulation. If you suddenly needed to support a different type of screen, for example, you would only need to change the SCREEN class.
NAME TYPE DESCRIPTION
READKEY INSTANCE METHOD Read a key
READSTATUS INSTANCE METHOD Read keyboard status
RESET INSTANCE METHOD Reset keyboard
NAME TYPE DESCRIPTION
WRITECHAR INSTANCE METHOD Write character
SETATTR INSTANCE METHOD Set attribute
POSCURSOR INSTANCE METHOD Position cursor
CLRSCREEN INSTANCE METHOD Clear screen
CLRLINE INSTANCE METHOD Clear to end of line
STATUS INSTANCE METHOD Return screen's status
NAME TYPE DESCRIPTION
READKEY_ECHO INSTANCE METHOD Read a key and echo to screen
A text editor class can best be implemented with two independent classes-neither class is a child of the other. The LINE class handles one line of text. It displays the line, and allows changes to the line. The EDITOR class contains, among other things, an array of line objects. You can effect changes to the file by sending messages to an EDITOR object.
The EDITOR class also would duplicate most (if not all) of the messages that the LINE class accepts. The message would be passed to LINES[CURLINE] (that is, the current line object) directly.
To accept keyboard input, you could make yet another object. This object would create an EDITOR object and accept input from the keyboard (or a mouse, etc.). Each keystroke would be translated into the proper messages to the EDITOR object.
Notice that the objects in this example cooperate, but they are not directly related via a parent/child relationship. Objects that contain objects are useful in a variety of tasks.
NAME TYPE DESCRIPTION
TEXT INSTANCE VARIABLE Array of text in line
NRCHAR INSTANCE VARIABLE Length of TEXT
CURSOR INSTANCE VARIABLE Index of cursor in TEXT
INSERT INSTANCE METHOD Insert character at cursor
DELETE INSTANCE METHOD Delete character at cursor
OVER INSTANCE METHOD Replace character at cursor
LEFT INSTANCE METHOD Move cursor to the left
RIGHT INSTANCE METHOD Move cursor to the right
POS INSTANCE METHOD Move cursor to position
STORE INSTANCE METHOD Set TEXT to string
RECALL INSTANCE METHOD Return TEXT
NAME TYPE DESCRIPTION
LINES INSTANCE VARIABLE Array of LINE objects
CURLINE INSTANCE VARIABLE Index of current line
NLINES INSTANCE VARIABLE Size of LINES array
READFILE INSTANCE METHOD Read file into LINES
WRITEFILE INSTANCE METHOD Write LINES to file
DELLINE INSTANCE METHOD Delete line
INSLINE INSTANCE METHOD Insert blank line
UP INSTANCE METHOD Move to previous line
DOWN INSTANCE METHOD Move to next line
GOLINE INSTANCE METHOD Goto specified line