home *** CD-ROM | disk | FTP | other *** search
- Introduction to Object-Oriented Programming
- by Bruce Newburger, Zack Urlocker
- Copyright(c) 1989 The Whitewater Group, Inc.
-
- Overview
- --------
- Object-oriented programming (OOP) represents a new, more
- productive approach to solving problems. Rather than working
- with traditional procedures and separate data structures, we
- create objects which encompass both the data and the
- operations. Object-oriented programming languages reduce the
- amount of code that needs to be written and maintained by
- enabling the programmer to create classes of reusable objects
- which encapsulate behavior and ensure data abstraction.
-
- Object-oriented programming is easy to learn since it is based
- on a few simple yet powerful concepts. Many programmers find
- object-oriented programming to be a natural extension to how
- they think.
-
- We will define objects, classes, messages and inheritance using
- understandable non-programming examples. We will often refer
- to the Actor(R) language for programming examples of object-oriented
- concepts. Actor is an interactive object-oriented language for the
- development of Microsoft Windows(tm) applications.
-
- History of OOP
- --------------
- Object-oriented programming was first introduced in the Simula
- language in 1967. Smalltalk, developed at Xerox Palo Alto
- Research Center (PARC), later refined the concepts and became
- the first pure object-oriented language. Since then, many
- other object-oriented languages have emerged including Actor,
- C preprocessors such as C++ and Objective-C, and extensions to
- Lisp such as Flavors and Scheme.
-
- In order for a language to be considered object-oriented it
- must meet three criteria:
-
- 1] encapsulation of data and instructions into units of
- functionality called objects
- 2] inheritance of functionality through a class hierarchy
- 3] dynamic runtime binding of messages sent to objects
-
- Languages such as Ada and Modula-2, which are sometimes called
- object-oriented, meet the first criteria but fail the second
- and third.
-
- Pure object-oriented languages such as Actor meet all three
- criteria and have the advantage of a consistent world in which
- everything is an object and all operations take place by
- sending messages to objects. This makes learning the language
- and debugging programs easier.
-
- Hybrid languages such as C++ add objects to standard C,
- providing the mixed blessing of being able to freely mix
- object-oriented C with traditional C. This compromises some of
- the power of object-oriented programming. For example, classes
- are not objects and dynamic binding is limited due to the
- constraints of C.
-
- When selecting an object-oriented language you should consider
- factors such as:
-
- 1] ease of learning
- 2] predefined classes
- 3] programming environment and tools
- 4] ease of debugging
- 5] ability to rapidly prototype and test code
- 6] execution speed
- 7] memory management
- 8] access to existing libraries
- 9] ability to create a standalone, distributable application
-
- One of the goals of developing Actor was to provide a rich
- class library and interactive environment that improved
- programmer productivity without compromising efficiency.
-
-
- Object-oriented Programming
- ---------------------------
- The basis of object-oriented programming is the creation and
- management of objects. An object is a programming entity that
- is designed to closely resemble real-life objects. An object
- has attributes and responds to instructions. For example, in a
- check-writing program, a check object has these attributes:
- amount, check number, date, to whom, and comment. It responds
- to these instructions: write, cash, sign, record.
-
- The advantage of breaking down a problem in terms of objects is
- the way in which we represent data. In the check-writing
- problem above, the data is the amount, the check number and so
- on. The rest of the program can access the data only through
- the instructions like write and cash. In effect, we have
- encapsulated access to the data since a check object is both
- the data and the instructions that act upon it.
-
- In Actor, many entities that you would normally think of as
- data structures are actually objects. For example, integers,
- characters, arrays, strings and files are all objects. There
- are also objects corresponding to more sophisticated data
- structures such as stacks, queues, look up tables, windows,
- dialog boxes and so on.
-
- A non-programming example of an object as a functional entity
- is a car. A car object has attributes such as the
- transmission, year and color. In addition, the car object
- responds to certain instructions, such as go (step on the gas),
- stop (step on the brake), left (turn the wheel left) and right
- (turn the wheel right). When you step on the gas, you need not
- be concerned with the internal workings of the engine. All
- cars are driven the same way, regardless of the particular make
- or model. The ability to manipulate an object's data without
- knowledge of the data's internal format is called data
- abstraction.
-
- Objects can be made up of primitive data, indexed data or named
- data. Primitive data is embedded directly in the structure of
- objects such as numbers, characters and symbols so that access
- is as efficient as possible. Indexed data is used in objects
- such as arrays or strings where there are several items that
- make up an object. We can refer to indexed data in an object x
- via the familiar array notation x[i]. Objects can also be made
- up of named instance variables, which refer to other objects.
- For example a car object myCar will have instance variables
- paint, year and transmission. We can refer to the instance
- variables via dot notation such as myCar.year, although
- generally we will want to encapsulate access to private data.
-
- To review, an object is the basic building block of an object-
- oriented programming system. Objects provide a simple means to
- represent the entities of a real world problem in terms of a
- programming entity. An object has instance variables that
- describe its data, and instructions that define operations to
- be performed on the object. In general, objects may have named
- instance variables, indexed variables, both or neither,
- depending on what is required. The instructions are part of
- the object and are tailored to the object's internal
- representation.
-
-
- Objects are Grouped in Classes
- ------------------------------
- In object-oriented programming, we call a type a class. Each
- object belongs to one and only one class. We say that an
- object is an instance of the class it belongs to. There can be
- many different classes; Actor includes over a hundred
- predefined classes that you can use in your programs. Think of
- a class as an object template, or an object factory. Every
- object of a given class has the same data format and responds
- to the same instructions. In the car example, we might have a
- class called Ford. Ford is a class of car, and all Ford cars
- belong to the class.
-
- There is no limit to the number of objects you can create of a
- given class. The instructions that an object can respond to
- are managed by the class. The data associated with a
- particular object is managed by the object itself. For
- example, you might have a red Ford Cortina and a blue Ford
- Mustang.
-
- Thus, the objects you use in your programs come from classes.
- You can use any of the predefined classes that are loaded in
- the system. You can also create your own classes.
-
-
- Objects Respond to Messages
- ---------------------------
- Objects perform operations in response to messages. For
- example, when we press on the brake we send a stop message to a
- car object. The car object's brake system is authorized to
- handle the stop message because it consists of specialized
- parts like brake pads and hydraulics. By following a set of
- conventions, or protocol, the Actor programmer is protected
- from unauthorized data manipulation. Too often, procedural
- programmers put their hands right to the wheel and get burned.
-
- A message is different than a subroutine call in that different
- objects can respond to the same message in different ways. For
- example, cars, motorcycles and bicycles will all respond to a
- stop message, but the operations they perform are object-
- specific.
-
- Examples of messages in Actor are shown below.
-
- printLine(x); /* whatever x is, tell it to print */
- draw(item, hDC); /* tell the item to draw itself */
- close(device); /* send a close message to device */
- y := 5*7 /* tell 7 to multiply by 5 */
-
- In the examples above the receiver of the message is the first
- parameter in parenthesese; arguments may follow the receiver.
- Note that the message makes no assumptions about the class of
- the receiver or of the arguments; they are simply objects. It
- is the receiver's responsibility to respond to a message in an
- appropriate manner. This gives us a great deal of flexibility
- since different objects can respond to the same message
- differently. This is known as polymorphism, literally meaning
- "many behaviors."
-
- Polymorphism allows us to write generic reusable code more
- easily, since we can specify general instructions and delegate
- the implementation details to the objects that are involved.
- Since there are no assumptions about the classes of objects
- involved, there are fewer dependencies in the code and
- maintenance is easier.
-
- Objects respond to messages according to methods that have been
- defined in their class. For example if a Cube object receives
- a draw message, then the class Cube (or one of its ancestors)
- must define a draw method. A method definition corresponds to
- a procedure definition in other languages. A sample method
- definition in Actor is shown below.
-
- /* This method defines how a Cube object will respond to
- a draw message. The argument hDC is a handle to a
- Windows display context where the drawing takes place.
-
- A cube object is made up of two rectangles called front
- and rear. A cube is drawn by drawing the front and rear
- faces and then connecting them.
-
- self refers to the cube that received the draw message.
- */
- Def draw(self, hDC)
- {
- draw(front, hDC);/* tell the front to draw */
- draw(rear, hDC); /* tell the rear to draw */
- drawConnections(self, hDC); /* connect the faces */
- }
-
-
- Class Hierarchy
- ---------------
- An object-oriented system has the responsibility of organizing
- and managing the one-hundred or more classes that your programs
- will use. It does this by organizing classes into a hierarchy.
- At the top of the hierarchy is the most general classes and at
- the bottom are the most specific classes.
-
- For example, in the car example, Ford is a class that defines
- what Ford car objects are. But there are classes of Ford car
- objects that are more specialized Fords, such as Taurus,
- Escort, and Thunderbird. These classes define Fords in a much
- more specialized manner than does the Ford class itself. So we
- say that the classes Taurus, Escort and Thunderbird descend
- from class Ford and the Ford class is their ancestor class. In
- some object-oriented languages the terms superclass and
- subclass or base class and derived class are used instead of
- ancestor and descendant.
-
- But there can be classes more general than Ford. For example,
- Ford might descend from class Car, which would, in turn,
- descend from class Vehicle, and so on. Class Car defines how a
- car behaves, class Ford defines how Ford cars behave in
- addition to cars in general, and class Escort defines how
- Escorts behave in addition to Ford cars in general.
-
- Of course, if all we wanted was a Ford Escort object, we would
- write only one class, called Escort. This class would define
- exactly how a Ford Escort car operates. This methodology is
- limiting because if we decide later to create a Ford Taurus
- object we will have to duplicate most of the code which
- describes first how a vehicle behaves, then how a car behaves,
- and then how a Ford behaves. This is what is done in a
- procedural language. An object-oriented language eliminates
- duplicated effort by allowing classes to share behaviors.
-
- You might find it strange to define a Car class. After all,
- what is an instance of the Car class. We have no such thing as
- a generic car; all cars must be of some make and model. In the
- same way, we have no instances of the Ford class. All Fords
- must belong to one of the subclasses Escort, Taurus or
- Thunderbird. We call classes like Car and Ford formal classes.
- We never create instances of formal classes. Formal classes
- are used to share common behavior among classes.
-
- A real Actor example of formal classes is the part of the Actor
- class tree that defines various collections including arrays,
- sets, strings, dictionaries and so on. The formal class
- Collection defines the common behavior among the classes and
- has descendant classes Set, Bag, IndexedCollection and
- KeyedCollection. IndexedCollection is a formal class that
- defines the common behavior among collections that use integer
- indices. It has descendant classes such as Array, String,
- Struct and OrderedCollection. KeyedCollection is a formal
- class that allows arbitrary keyed access and has descendant
- classes such as Dictionary, Frame and Slot.
-
-
- Inheritance
- -----------
- Inheritance is a mechanism for sharing behaviors between
- classes. The behavior of a class's instances is defined in
- that classes methods. But a class also inherits the behavior
- of all of its ancestors.
-
- For example, the class Car defines how cars in general behave.
- The class Ford inherits the general car behavior from class
- Car, and adds behavior that is specific to Ford cars. But the
- Ford class does not have to redefine the car behavior. Next,
- the Escort class inherits behavior of cars from class Car, and
- behavior of Fords from class Ford. It adds the behavior
- specific only to Escorts.
-
- For example, assume that all Fords use the same braking system.
- Then the method brake would be defined in class Ford. When we
- step on the brake pedal of an Escort, a stop message is sent.
- However, Escort does not define a stop method, and the search
- continues in class Escort's direct ancestor, the class Ford.
- The stop method of class Ford is then invoked.
-
- In a similar way, Escort can inherit behaviors from the Car and
- Vehicle classes. The behaviors of any given class is really an
- amalgamation of the behaviors of all of its ancestors. This
- straightforward process of inheritance prevents you from having
- to re-invent the wheel, or the brakes, for that matter.
-
- Let's say that most Ford cars use the same braking system, but
- the Thunderbird has its own, anti-lock braking system. In this
- case, the Thunderbird class would redefine the stop method.
-
- Thus the brake method of the Ford class would never be invoked
- by Thunderbirds. However, its existence higher up in the class
- hierarchy does not cause a conflict. Other Ford cars would
- continue to use the standard braking system.
-
-
- Single Inheritance vs. Multiple Inheritance
- -------------------------------------------
- Actor, like most object-oriented languages, operates according
- to single inheritance. That means that the system searches for
- methods directly up the class hierarchy, first in the class of
- the instance, then in that class's direct ancestor, and so on
- up the line. Each class directly descends from only one
- ancestor class.
-
- In a scheme called multiple inheritance, used in some object-
- oriented versions of Lisp, a class can descend from many
- unrelated classes. Multiple inheritance can make it easy to
- combine behaviors of several classes at the expense of having
- to specify how conflicts are resolved.
-
- Although there are some limitations to single inheritance, you
- can often achieve the benefits of combined behavior by adding
- instance variables of other classes. This is not as general a
- solution as multiple inheritance, but it avoids some of the
- complexity of conflict resolution.
-
-
- Encapsulation
- -------------
- Encapsulation is a design goal of object-oriented programming.
- It is achieved by allowing access to data only through its own
- methods. This ensures that instructions are operating on the
- proper data. No other parts of the program can operate
- directly on another object's data. An object's internal format
- is insulated from other objects. An important factor in
- achieving encapsulation is designing different classes of
- objects that operate using a common protocol. That means many
- objects will respond to the same messages but will implement
- their own methods. That way, your program can send a generic
- message and leave the implementation up to the receiving
- object. This reduces interdependencies, and increases
- interchangability and reusability.
-
- If we bring to mind the car example, we can think of a car's
- engine as being encapsulated. Although engines may differ in
- implementation, they all interface with the driver through a
- common protocol: step on the gas for more power, and let up on
- the gas for less power. Since all drivers know this protocol,
- all drivers know how to drive all cars. It doesn't matter what
- engine is in the car, that detail is insulated from the rest of
- the car and the driver. This makes cars more easily
- interchangeable and maintainable.
-
- Data abstraction is the result of good object-oriented code
- that takes advantage of encapsulation and polymorphism. Data
- is abstracted when it is shielded by a full set of methods.
- Only a class's methods utilize the details of the class's data
- format or contents.
-
-
- Summary
- -------
- Object-oriented programming is a significant departure from
- procedural programming. Rather than treat data and procedures
- separately, they are closely linked into what are known as
- objects. The main advantage of object-oriented programming is
- the ability to reuse code and develop more maintainable systems
- in a shorter amount of time. This is achieved by enabling the
- programmer to create reusable classes that inherit the behavior
- of ancestor classes. Good object-oriented programming makes
- use of encapsulation and polymorphism to provide abstract data
- types.
-
- Actor is a registered trademark and The Whitewater Group is a registered
- service mark of The Whitewater Group, Inc. Other product names may be
- trademarks of their respective owners.