Chapter II.7. Breaking a Large Program into Objects

Breaking a large program into multiple subprograms makes programming easier. Instead of trying to write a single, monolithic chunk of code, you just have to write small subprograms that work as building blocks that you can stack together to create a much larger program.

Unfortunately, computer scientists found that just dividing a large program into multiple subprograms didn't magically solve all the problems of creating software. Some of the most prominent problems of subprograms include

  • Interconnectedness: Rather than act as independent entities, subprograms are often allowed to interfere with other parts of a program. Not only does this cause problems in tracking down problems (bugs), but it also prevents subprograms from being reused easily in other projects. Instead of easily sliding a subprogram out of a program like a building block, it's more like ripping a plant out of the ground by its roots.

  • Task-orientation: Subprograms focus on solving one specific task. Unfortunately, trying to understand how this one task fits into the overall design of a large program can be confusing, much like trying to understand how a car works by studying a single gear. As a result, subprograms make large programs hard to understand and modify. Not only do you not know how a subprogram works with the rest of the program, but you also don't know how changing a subprogram might inadvertently affect other parts of the program.

  • Reusability: Theoretically, you can yank out a subprogram and reuse it in another program. However, if you copy and later modify a subprogram, you now have two nearly identical copies of the same subprogram. If you find a problem in the original subprogram, you now have to find and fix that same problem in any copies you made of that subprogram — provided you can find them all in the first place.

To overcome the limitations of subprograms, computer scientists invented object-oriented programming (abbreviated as OOP). Like structured programming, which encourages you to break a large program into subprograms, OOP encourages you to break a large program into smaller parts, or objects.

Note

Object-oriented programming has actually been around since 1962 when two Norwegian computer scientists Ole-Johan Dahl and Kristen Nygaard developed a language called SIMULA, which was designed to help simulate real-world events. It took object-oriented programming nearly 40 more years to finally get accepted as a practical tool, so just because an idea is proven to work doesn't mean people will accept it if they can continue being comfortable (and getting paid) to keep doing something that doesn't work.

How Object-Oriented Programming Works

Like subprograms, objects divide a large program into smaller, interchangeable parts. The main difference is that subprograms divide a program into separate tasks whereas objects divide a program into real-world items.

For example, consider a hotel reservation program used by the front desk when a guest checks in. Dividing this problem into tasks might create the following:

  • Subprogram #1: RoomAvailable (Checks if a hotel room is available)

  • Subprogram #2: RoomBeds (Checks if the room has 1 or 2 beds)

  • Subprogram #3: RoomType (Checks if it's a smoking or a nonsmoking room)

  • Subprogram #4: RoomPrice (Checks the price)

Dividing this problem into objects, you could create the following:

  • Object #1: Guest

  • Object #2: Front desk clerk

  • Object #3: Hotel room

Figure 7-1 shows how a task-oriented solution might break a program into multiple subprograms. The main program works by running each subprogram, one at a time, with each subprogram performing a specific task (such as determining whether a room is smoking or nonsmoking).

Dividing a program into tasks can obscure the actual purpose of a program.

Figure II.7-1. Dividing a program into tasks can obscure the actual purpose of a program.

Figure 7-2 shows an equivalent object-oriented solution to the same program where each object represents a real-world item. Rather than having a single main program controlling multiple subprograms (like one boss controlling a dozen subordinates), OOP divides a program into multiple objects that pass messages to one another (like having a bunch of workers cooperating with one another as equals).

Although both subprograms and objects solve the same problem, they use different solutions. Object-oriented programming is basically a different way of thinking about how to solve problems.

OOP divides a large program into objects that behave like their real-world counter-parts.

Figure II.7-2. OOP divides a large program into objects that behave like their real-world counter-parts.

Warning

Objects aren't an alternative to subprograms. Subprograms solve a single task. Objects just organize related subprograms together.

Warning

There's no single "right" way to divide a large program into objects. Two programmers tackling the same problem will likely divide the same program into different objects. The way you define your objects reflects how you view a particular problem.

Every object consists of two parts, as shown in Figure 7-3:

  • Data (also called properties)

  • Subprograms (also called methods)

The parts of a typical object.

Figure II.7-3. The parts of a typical object.

Objects contain two types of data:

  • Public data is accessible by other parts of the program.

  • Private data within the object is hidden from the rest of the program.

Objects contain two types of subprograms:

  • Public subprograms allow other parts of a program to control an object.

  • Private subprograms are used by an object to calculate a result needed by its public subprograms (methods).

Warning

The difference between public and private data and subprograms is accessibility:

  • Public data and subprograms are what the rest of a program can "see" and use in an object:

    • Public data typically describes the object in some way. For example, a video game program might create an object that represents a monster. This object may need data, representing X and Y coordinates, to define the monster's location on-screen.

    • Public subprograms (methods) allow other parts of a program to manipulate an object. For example, an object representing a monster might include a Move subprogram that can change the value of the object's X and Y coordinates (to determine where to display the cartoon monster on-screen).

  • Private data and subprograms are what an object uses to do something useful, so the object doesn't need to allow other parts of the program to access this information.

The Monster object might contain a private subprogram that calculates exactly how the Monster object moves. Because other parts of the program don't need to know exactly how the Monster object calculates its movement, this type of information would be private and hidden from the rest of the program.

Ultimately, OOP is another way to make programming easier. Just as high-level languages (like BASIC) simplify programming by using real-life commands (such as PRINT), so does OOP simplify organizing programs by modeling real-life items. The three advantages that objects have over ordinary subprograms include

  • Encapsulation

  • Inheritance

  • Polymorphism

Warning

Object-oriented programming provides tools for making programming easier, but it's still possible to write horrible software with OOP. Think of OOP like lines painted on the highway. If you follow the lines, you probably arrive safely at your destination, but if you ignore the lines and do whatever you want, you probably crash your car. Like traffic lines painted on the road, OOP guides you into writing software that can be created and modified easily, but you can still mess up things if you're not careful.

Encapsulation Isolates Data and Subprograms

Subprograms have two problems. First, subprograms can work with data from any part of a program. That's what makes subprograms useful, but that's also what makes subprograms harder to modify and fix. If you don't know what data a subprogram might manipulate and when, any changes you make to that subprogram could affect a program in unpredictable ways.

For example, suppose someone writes a weather forecasting program that has a subprogram for predicting tomorrow's temperature measured in Fahrenheit. What happens if another programmer modifies this subprogram to forecast temperatures in Celsius?

Figure 7-4 shows two phases of a program:

The upper phase shows the main program sending the current temperature (32 degrees Fahrenheit) to the forecasting subprogram, which then returns its prediction (as 30 degrees Fahrenheit).

The lower phase shows the same program except now the forecasting subprogram has been modified to return Celsius temperatures. So now when the main program sends the current temperature (in Fahrenheit) to the forecasting subprogram, this subprogram returns its forecast in Celsius. The main program now uses this faulty value.

Changing a subprogram can wreck a perfectly working program.

Figure II.7-4. Changing a subprogram can wreck a perfectly working program.

This problem occurs because the forecasting subprogram has no idea how its data is being used by another part of the program. Object-oriented programming can partially solve this problem by organizing data, and all the subprograms that manipulate that data, into a single location, or an object. By grouping data and all the subprograms that manipulate that data in one place, it's much easier to understand how that data is being used.

The whole idea behind an object is to isolate and "hide" data and subprograms by using encapsulation. Encapsulation acts like a wall, as shown in Figure 7-5, that wraps around data and subprograms to

  • Keep other parts of a program from manipulating data inside an object.

  • Keep subprograms inside that object from manipulating data outside that object.

  • Keep programmers from modifying code stored in another object.

Shielding data inside an object

Think of data as a wallet full of cash. The more people who handle your wallet before giving it back to you, the greater the chance that someone takes money out of that wallet (manipulating the data). Ideally, you want as few people to handle your wallet as possible and if people absolutely must handle your wallet, you want them close enough so you can keep an eye on them.

Encapsulation isolates a chunk of code as an independent object.

Figure II.7-5. Encapsulation isolates a chunk of code as an independent object.

That's the same idea behind encapsulating data inside an object. In a program divided into multiple subprograms, data gets passed around like a hot potato. The more subprograms capable of changing a chunk of data, the more likely one of those subprograms can accidentally change that data incorrectly.

By encapsulating data inside of an object, you prevent anything outside that object from manipulating the data.

Grouping subprograms inside of an object

After you isolate data inside an object, you also need to isolate all the subprograms that manipulate that data inside that same object. By storing all subprograms that manipulate the same data, objects make it easy to isolate any problems.

If data inside an object gets messed up, the faulty subprogram can be located only inside that same object. This makes troubleshooting easier. In comparison, if data gets messed up in a non-object-oriented program, the faulty subprogram could be located anywhere. Trying to find a faulty subprogram in an object is like trying to find your lost keys in your apartment. Trying to find a faulty subprogram in an entire program is like trying to find your lost keys in a 20-story apartment building.

Protecting code from other programmers

Objects isolate data from other parts of the program, but objects can also isolate subprograms from other programmers.

Without objects, someone might write a useful subprogram that everyone else working on the program can use. One programmer might find that subprogram perfect whereas a second programmer might find that subprogram doesn't quite do what he wants it to do, so he goes into the subprogram and changes the code.

These changes wreck the subprogram for the first programmer, who now has to go back and fix the changes made by the second programmer. These changes make the subprogram work good for the first programmer, but now wreck the subprogram for the second programmer, and so on in an endless cycle.

The problem is that the more people you have working on the same program, the more likely someone might accidentally modify one part of a program without notifying the other programmers. Even one change in a program can affect another part of that same program, so object-oriented programming defines distinct boundaries that keep programmers from modifying code stored in objects created by someone else.

When creating an object-oriented program, every programmer is given control of certain objects and no one is supposed to modify the code in any objects but his own.

Objects let you physically store the source code for your entire object in a separate file, called a class file or just a class. At this point, a class is no different than storing a group of related subprograms in a separate file and keeping other programmers from modifying that separate file. However, the difference becomes more apparent when you want to reuse code.

Warning

Encapsulation serves two purposes:

  • Protects data from being changed by other parts of a program

  • Protects subprograms from being changed by other programmers

Sharing Code with Inheritance

After programmers write some useful subprograms, they often store those subprograms in separate files for other programmers to use. However, no one is supposed to modify these subprograms.

So what happens if someone creates a subprogram that almost does what you need, but not quite? You can't modify the subprogram without the risk of wrecking it for other parts of the program, but you can copy that subprogram and then modify that copy. Now you'll have two separate and nearly identical copies of the same subprograms, as shown in Figure 7-6.

If you modify a subprogram, you need to create a separate copy of that subprogram and modify that copy.

Figure II.7-6. If you modify a subprogram, you need to create a separate copy of that subprogram and modify that copy.

What happens if the original subprogram (that you copied) gets modified to make it even more awesome and useful? Now you're stuck with two equally unappealing choices with your modified version of that same subprogram:

  • Dump your modified subprogram, copy the new modified subprogram, and re-modify this new version.

  • Modify your subprograms yourself to incorporate the changes made to the subprogram you originally copied.

Neither solution will be easy because with the first option, you must modify the revised original subprogram all over again. If you made extensive modifications to that subprogram, you'll have to make those same extensive modifications once more. Each time the original subprogram gets modified, you'll have to repeat this step over and over again.

The second option is just as difficult because now you have to study the changes made in the original subprogram and add those changes to your modified subprogram. If you do this incorrectly, your modified version won't work right. Each time the original subprogram gets modified, you'll have to keep up with those changes so you can add them to your modified version of that same subprogram.

Note

Sound like a lot of trouble? It is, which is what makes inheritance so attractive. With inheritance, you don't make multiple, physical copies of subprograms. Instead, you first store the subprogram in an object (a class file).

Next, you inherit that object. Inheritance tells the computer to copy an object (along with all the subprograms stored inside that object) and store all the data and subprograms from that first object into that second object.

Physically, this second object contains no code of its own. Instead, the second object points to the code of the original object, as shown in Figure 7-7.

When you run subprograms in this second object, this second object tells the computer, "Hey, those subprograms are really stored in this other object that I inherited them from."

Inheritance offers two advantages:

  • Because it doesn't make multiple copies of the same subprograms, inheritance saves space.

  • Because only one copy of a subprogram physically exists, inheritance makes it easy to update a subprogram.

Inheritance lets you reuse another object's subprograms without physically copying them.

Figure II.7-7. Inheritance lets you reuse another object's subprograms without physically copying them.

Make a change to the original subprogram, and those changes instantly appear in any object that inherited that subprogram. The reason for this instant update is because all those other objects always point to the same subprogram in the first place.

Inheritance lets you reuse code from another object without physically copying that code. Now if you can add subprograms to your new object, your new object contains only your new subprograms, as shown in Figure 7-8.

Objects contain code that's unique to only that object.

Figure II.7-8. Objects contain code that's unique to only that object.

By keeping the amount of code stored inside each object to a minimum, object-oriented programming makes it easy to understand how each object works. Through inheritance, OOP makes it easy to update one subprogram that's reused in other objects.

As a result, inheritance makes reusing objects (and their subprograms) practical and modifying those objects' subprograms fast, simple, and easy.

Warning

Inheritance offers the convenience of reusing code without the inconvenience of updating that code in multiple locations.

Polymorphism: Modifying Code without Changing Its Name

Besides reusing existing subprograms (without modifying them) and adding new subprograms to an object, you can also modify an inherited subprogram through polymorphism.

Polymorphism lets you inherit a subprogram from another object and then replace the code in that subprogram with brand new code. So essentially all you're really reusing is the original subprogram's name, as shown in Figure 7-9.

Polymorphism lets you reuse a subprogram name in another object.

Figure II.7-9. Polymorphism lets you reuse a subprogram name in another object.

The purpose of polymorphism is to let multiple objects use the same descriptive subprogram name. Normally, two subprograms can't share the same name. Otherwise, when you call a subprogram by name, the computer doesn't know which subprogram you actually want to use.

However, when you call a subprogram inside an object, you must specify both the object and the subprogram name stored inside that object. So if you wanted to run the Move subprogram inside an Airplane object, you could call that subprogram by using this command:

Airplane.Move

This Airplane.Move command might tell the computer to move a cartoon airplane in a video game. Now what if this video game needs to display a spaceship on-screen? You could write a new Spaceship object from scratch (which takes time) or you could just inherit all the code stored in the Airplane object to create a Spaceship object.

Of course, a spaceship moves differently than an airplane, so you could inherit the Move subprogram from the Airplane object, modify that subprogram's code, and you've instantly created a new Spaceship object in very little time. Now you can use the same subprogram name (Move) to change the position of two different objects, such as

Airplane.Move
Spaceship.Move

Warning

Encapsulation protects data and subprograms from being changed. Polymorphism reuses and modifies code without affecting the original source code. Inheritance reuses code without physically copying it.

Design Patterns

There's no single "right" way to divide a program into objects. When faced with the same problem, two programmers may divide up the program into completely different objects.

However, the more that programmers used object-oriented programming, the more they noticed that some ways of dividing a program into objects worked better than other ways. These specific ways of dividing a program into objects is called a design pattern.

A design pattern provides a blueprint for the best way to divide specific types of problems into objects. Because these design patterns have been proven already to work, you can use a design pattern to help solve your particular problem.

Without design patterns, you're forced to design objects by yourself and risk choosing a faulty design that you wouldn't know about until you might have already created most of your program.

Three examples of different design patterns (and their unusual names) include

  • Interface pattern

  • Flyweight pattern

  • Memento pattern

An interface pattern defines an object that simplifies access to something else. For example, suppose someone has written a library of useful subprograms. Rather than let other programmers access these subprograms directly, an interface pattern defines an object to provide access to these subprograms instead. By doing this, an interface pattern keeps your program focused on using object-oriented features.

So this library might contain subprograms for displaying graphics and calculating mathematical equations. You could use the interface pattern to define one object for accessing the graphics subprograms and a second object for accessing the mathematical equations subprograms, as shown in Figure 7-10.

An interface pattern provides an object-oriented interface to a non-object-oriented item, such as a library of subprograms.

Figure II.7-10. An interface pattern provides an object-oriented interface to a non-object-oriented item, such as a library of subprograms.

A flyweight pattern is used to create multiple objects. For example, you could create a word processor with every character defined as an object that contains formatting information, such as font, font size, underlining, and so on. However, a typical word processor document would contain thousands of objects (characters), and because each object gobbles up memory, creating so many objects would likely swamp the computer's memory.

The flyweight pattern solves this problem by removing repetitive information from multiple objects (such as formatting information) and replacing it with a pointer to another object that contains this information, as shown in Figure 7-11.

The flyweight pattern simplifies objects that contain repetitive information.

Figure II.7-11. The flyweight pattern simplifies objects that contain repetitive information.

A memento pattern is used to allow an object to restore itself to a previous state. For example, you might use an object to represent a line in a drawing program. If you change that line to make it thicker or a different color, those changes are stored in the line object. If you suddenly decide you want to undo your changes, your program can restore those changes by using the memento object, as shown in Figure 7-12.

The memento pattern uses one object to store information about another object's previous state.

Figure II.7-12. The memento pattern uses one object to store information about another object's previous state.

These are just a sampling of different design patterns available and how they solve specific problems that occur when using object-oriented programming. Before rushing out to create an OOP, take some time to learn about design patterns. That way you can pick a design pattern that solves your program's specific needs and you don't risk designing a program that doesn't work right because you didn't know anything about design patterns.

Warning

Design patterns are guidelines for creating an OOP program, so it's possible to use multiple design patterns in different parts of a program.

Object-Oriented Languages

Two types of object-oriented programming languages exist: Hybrid and pure languages.

Hybrid languages

A hybrid language is simply a language originally designed without object-oriented features, but with object-oriented features added on. Some popular examples of hybrid languages include

  • BASIC (Visual Basic and REALbasic)

  • C (C++, C#, and Objective-C)

  • Pascal (Delphi)

  • Ada (ObjectAda)

  • COBOL (Object Oriented COBOL)

Because hybrid languages are based on popular languages, they make it easy for current programmers to understand and use. Unlike "pure" object-oriented languages that force you to design a program completely around objects, hybrid languages let you write programs by using the traditional task-oriented, subprogram approach and only using object-oriented features sparingly until you get comfortable with using and designing programs with OOP.

Because hybrid languages are based on languages that have been around for decades, a hybrid language lets you take an existing program and add object-oriented features to it. COBOL programs have been around since the 1960s, so companies are reluctant to rewrite working programs in another language just to gain object-oriented features. Rather than rewrite a perfectly working COBOL program in C++, programmers can just use Object Oriented COBOL instead, which effectively extends the life of ancient COBOL programs.

Warning

Hybrid languages do have one major drawback. Because programs written in hybrid languages tend to be a mish-mash collection of traditional and object-oriented programming, they can be hard to understand and even harder to modify.

Pure languages

Although programmers can quickly adapt to the object-oriented language based on a language they already know, most programmers tend to stick with writing programs the way they've always done it, which often means not using object-oriented programming techniques at all or using the object-oriented features poorly.

To get around this problem, computer scientists have developed pure object-oriented languages, which forces programmers to use object-oriented techniques whether they like it or not. Some popular pure OOP languages include

  • Java

  • C#

  • Perl

  • Python

  • Smalltalk

By forcing you to use object-oriented programming techniques, pure object-oriented languages make sure that every program written in that particular language can be easily understood in terms of objects. A program written in a hybrid language can be as sloppy as a native Arabic-speaker writing a letter in both Arabic and English. A program written in a pure object-oriented language may be sloppy and poorly written, but it's like forcing a native Arabic-speaker to write a letter completely in English, so at least it's easier for English speakers to understand.

So which type of language should you learn and use? If you need to update programs written in older programming languages, like C, BASIC, or Pascal, you have no choice but to update those programs by using a hybrid language.

Ultimately, it's probably best to force yourself to know at least one pure object-oriented language so you fully understand the benefits of OOP and put those benefits into practical use. After you completely understand how to design and use object-oriented techniques, you're more likely to use OOP features in a hybrid language.

Warning

The programming language you use is less important than designing a program correctly from the start. Languages are tools to help you achieve a goal, so don't get caught up in the "religious" wars arguing whether one programming language is "better" than another. The "best" programming language is the one that makes you most efficient.

Disadvantages of object-oriented programming

Despite its clear-cut advantages, object-oriented programming isn't perfect and suffers its share of drawbacks:

  • OOP is best suited for organizing large programs. If you need to write a small program to make a printer work with an operating system, organizing your program into objects doesn't likely give you any benefits and may take more time to write.

  • OOP requires more memory to run than non-OOP programs. So if you're writing a small program that needs to be fast and use as little memory as possible, OOP actually makes your program harder to write and slower to run.

Like all programming techniques, such as structured programming, object-oriented programming isn't a magical solution for writing large programs flawlessly. Instead, object-oriented programming is more of a guideline for steering you into using proven techniques for organizing programs and making them easier to modify and update.

The ultimate goal of any programmer is to write software that works, is easy to fix and modify, and gets completed on time. If you can achieve these three goals on a consistent basis, you'll always have plenty of people willing to hire you at whatever salary you want.

Real-Life Programming Examples

To fully understand object-oriented programming, you need to see how to use OOP in a real programming language. Basically, the steps to using OOP involve

  • Defining an object with a class file

  • Creating an object based on a class

  • Using subprograms (methods) in an object

  • Inheriting an object

  • Using polymorphism to rewrite an inherited subprogram

Warning

Although the following examples use C++, don't worry about the particular syntax of each programming language example. Because every programming language uses different syntax and commands, focus on understanding the principles behind creating and using objects.

Defining an object with a class

To create an object, you must first create a class, stored in a separate file that defines

  • The data (properties) the object contains

  • The subprograms (methods) the object uses to manipulate its data

At the simplest level, a C++ class consists of the class keyword along with a descriptive name for your class, such as

class ClassName
{
};

So if you wanted to name your class animal, your class would now look like this:

class animal
{
};

Next, you need to define the public data (properties) and subprograms (methods) by using the public keyword. Then you must define the private data and subprograms by using the private keyword, such as

class animal
{
public:

private:

};

Underneath both the public and private keywords, you must declare your data and subprograms. If you wanted to define an X coordinate and Y coordinate variable as public and an X variable as privateh, you'd do this:

class animal
{
public:
  int x_coordinate;
  int y_coordinate;

private:
  int x;

};

Warning

Not all objects have both public and private data and subprograms. Some objects may just have public data and subprograms.

The preceding code creates three integer variables — x_coordinate, y_coordinate, and x. After you define the data your object will use, the next step is to define the subprograms it'll use, such as

class animal
{
public:
  int x_coordinate;
  int y_coordinate;

  void initial_position (int, int);
  void move(int, int);

private:
  int x;

};

The preceding code defines two subprograms (methods)initial_position and move. The initial_position and move subprograms both accept two integers in their parameter list. After you define the names of the subprograms you want to use, you have to write the actual code to make each subprogram work, such as

class animal
{
public:
  int x_coordinate;
  int y_coordinate;

  void initial_position (int, int);
  void move(int, int);

private:
  int x;

};


void animal::initial_position (int init_x, int init_y);
  {
  x_coordinate = init_x;
  y_coordinate = init_y;
  }

void animal::move (int new_x, int new_y);
  {
  x = 5;
  x_coordinate = x_coordinate + new_x + x;
  y_coordinate = y_coordinate + new_y;
  }

The initial_position subprogram defines an initial value for the two public variables x_coordinate and y_coordinate.

The move subprogram adds a new value to the current x_coordinate and y_coordinate values. This subprogram also uses the private variable (x), sets its value to 5, and uses that value to modify the value of the x_coordinate variable.

At this point, you've defined a class. The next step is to use this class in an actual program.

Warning

Every class file defines exactly one object. If a program needs a dozen different objects, you need to create a dozen different class files.

Creating an object from a class

Before you can use a class in your program, you need to

  • Tell your program which class file to use

  • Define an object based on the class file

If you stored the animal class in an "animal.h" file, you'd tell your main C++ program to use this "animal.h" file by using the include command like this:

#include "animal.h"

Next, you'd have to define an object name and declare it as an object based on a class. So if you wanted to create a cow object with the animal class, you'd use this:

#include "animal.h"

int main()
  {
  animal cow;
  return 0;
  }

Note

The #include "animal.h" command tells the program to use the class stored in the "animal.h" file. Most C++ also use multiple #include commands to make a program work, so the entire C++ program up to this point actually looks like this:

#include <stdio.h>
#include <iostream.h>
#include "animal.h"

int main()
  {
  animal cow;
  return 0;
  }

Running subprograms stored in an object

After you define an object in your main program, you can run a subprogram stored in that object. So if you wanted to run the initial_position subprogram, stored in the cow object, you'd identify the object name followed by the object's subprogram to run, such as

cow.initial_position (1,1);

The cow.initial_position (1,1) command tells the computer to use the cow object, run the initial_position subprogram stored in that cow object, and use the values 1 and 1.

If you wanted to run the move subprogram, you'd define the object name (cow) followed by the subprogram name (move) and wind up with a command like this:

cow.move (24,9);

Putting the whole program together, you might have something like this:

#include <stdio.h>
#include <iostream.h>
#include "animal.h"

int main()
  {
  animal cow;
  cow.initial_position (1,1);
  cout << "X-location = " << cow.x_coordinate << "
";
  cout << "Y-location = " << cow.y_coordinate << "
";
  cow.move (24,9);
  cout << "New X-location = " << cow.x_coordinate << "
";
  cout << "New Y-location = " << cow.y_coordinate << "
";
  cout << "
Press ENTER to continue..." << endl;
  getchar();
  return 0;
  }

If you ran this C++ program, the following would appear on-screen:

X-location = 1
Y-location = 1
New X-location = 30
New Y-location = 10

Press ENTER to continue...

Inheriting an object

To inherit an object, you must first create another class file. So if you wanted to create a human class and have it inherit from the animal class, you'd do this:

class human : public animal
{
};

The preceding code tells the computer that the human class inherits from the animal class. At this point, the human class is identical to the animal class.

To use the human class in the main program, you need to use the #include command, such as

#include <stdio.h>
#include <iostream.h>
#include "animal.h"
#include "human.h"

int main()
  {
  human cow;
  cow.initial_position (1,1);
  cout << "X-location = " << cow.x_coordinate << "
";
  cout << "Y-location = " << cow.y_coordinate << "
";
  cow.move (24,9);
  cout << "New X-location = " << cow.x_coordinate << "
";
  cout << "New Y-location = " << cow.y_coordinate << "
";
  cout << "
Press ENTER to continue..." << endl;
  getchar();
  return 0;
  }

In this version of the program, the cow object is declared to be a human class. Because the human class is identical to the animal class, this program runs identically as the preceding version where the cow object was declared as an animal class.

Although the human class behaves identically to the animal class, the human class is actually empty because it inherits all its code from the animal class. Now any code you add to the human class is unique just to that human class, such as

class human : public animal
{
public:
  int iq;

  void setiq (int);
  void iqtest (int);
};

void setiq (int startiq)
{
  iq = startiq;
}

void iqtest (int new_iq)
{
  iq = iq + new_iq;
}

Because this inherits all the code from the animal class, the human class is actually equivalent to the following, where the gray shaded code highlights the code unique to the human class:

class human
{
public:
  int x_coordinate;
  int y_coordinate;

  void initial_position (int, int);
  void move(int, int);

  int iq;

  void setiq (int);
  void iqtest (int);

private:
  int x;
};

void animal::initial_position (int init_x, int init_y);
  {
  x_coordinate = init_x;
  y_coordinate = init_y;
  }

void animal::move (int new_x, int new_y);
  {
  x = 5;
  x_coordinate = x_coordinate + new_x + x;
  y_coordinate = y_coordinate + new_y;
  }
void setiq (int startiq)
{
  iq = startiq;
}

void iqtest (int new_iq)
{
  iq = iq + new_iq;
}

As you can see, without inheritance, the code stored inside an object can soon grow out of control, but by using inheritance, each object contains only unique code.

An object that inherits code is treated no differently than an object created entirely from scratch. The following program shows how to use the human class:

#include <stdio.h>
#include <iostream.h>
#include "animal.h"
#include "human.h"

int main()
  {
  human cow;
  cow.initial_position (1,1);
  cout << "X-location = " << cow.x_coordinate << "
";
  cout << "Y-location = " << cow.y_coordinate << "
";
  cow.move (24,9);
  cout << "New X-location = " << cow.x_coordinate << "
";
  cout << "New Y-location = " << cow.y_coordinate << "
";
  cow.setiq (45);
  cout << "The cow's initial IQ is " << cow.iq << "
";
  cow.iqtest (26);
  cout << "The cow's IQ is now " << cow.iq << "
";
  cout << "
Press ENTER to continue..." << endl;
  getchar();
  return 0;
  }

Running this program displays the following on-screen:

X-location = 1
Y-location = 1
New X-location = 25
New Y-location = 10
The cow's initial IQ is 45
The cow's IQ is now 81

Press ENTER to continue...

Using polymorphism to rewrite an inherited subprogram

After you inherit code from another object, you can use polymorphism to rewrite a subprogram. To use polymorphism, you may need to define which subprograms (methods) in an object can be changed with polymorphism.

In C++, you define a polymorphic subprogram by using the virtual keyword. So if you wanted to make the Move subprogram polymorphic in the animal class, you'd have to modify the animal class like this:

class animal
{
public:
  int x_coordinate;
  int y_coordinate;

  void initial_position (int, int);
  virtual void move(int, int);

private:
  int x;

};

After you define that the Move subprogram is polymorphic and can be changed inside an object, the second step is to use the virtual keyword a second time to identify the new version of the subprogram.

So if you want to change the Move subprogram inside the human class, you'd have to use the virtual keyword again like this:

class human : public animal
{
public:
  int iq;

  void setiq (int);
  void iqtest (int);
  virtual void move (int, int);
};

void setiq (int startiq)
{
  iq = startiq;
}

void iqtest (int new_iq)
{
  iq = iq + new_iq;
}
void move (int new_x, int new_y)
{
  x_coordinate = new_x * 2;
  y_coordinate = new_y * 2;
}

After identifying the polymorphic subprogram with the virtual keyword, you then need to rewrite the Move subprogram. In the preceding example, the new Move subprogram accepts two numbers (new_x and new_y), multiplies them by 2, and uses that result for the cow object's new X and Y coordinates.

Warning

Not every object-oriented language requires you to identify polymorphic subprograms. Some languages let you inherit and modify subprograms without identifying them first.

So running the main program would now print the following on-screen:

X-location = 1
Y-location = 1
New X-location = 48
New Y-location = 18
The cow's initial IQ is 45
The cow's IQ is now 81

Notice that the main program now uses the Move subprogram stored in the human class, which multiplies each number by 2. So the cow.move (24, 9) command sets the cow's x_coordinate to 48 (24 * 2) and the y_coordinate to 18 (9 * 2).

Although these examples use C++, the basic steps to using objects remain the same:

  1. Create a class that defines the data and subprograms used by an object.

  2. Create one or more additional classes that inherit code from another class.

  3. Use polymorphism to rewrite code inherited from another object.

  4. Declare an object as a specific class type.

  5. Use an object's subprograms to manipulate that object's data.

Warning

Object-oriented programming can help you design large programs faster, but ultimately, your own skill as a programmer determines the quality of your programs.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset