Chapter 21

What Is Object-Oriented Programming?

In This Chapter

arrow Abstracting away the details

arrow Contrasting the object-oriented approach with the functional approach

arrow Classifying things

Examples of objects abound in everyday life. Right in front of me is a chair, a table, a computer, and a red Starbucks mug. I have no trouble grouping these objects into taxonomies based on their properties. For example, the mug is a container, it’s also a thermal insulator, so I can use it to hold hot or cold things, and it has mass, so that I can use it as a paperweight or to throw at the dog. Object-oriented programming applies this view of the world to that of programming. To explain what I mean, let me start with a story.

Abstraction and Microwave Ovens

Sometimes, when my son and I are watching football, I whip up a batch of nachos. Nothing fancy, mind you — I dump some chips on a plate, throw on refried beans, cheese, and a batch of jalapeños, and nuke the lot in the microwave oven for five minutes. To use the oven, I open the door, place the nachos inside, punch some buttons on the front, and hit start. After a few minutes, the bell rings to tell me they’re done. If I do something wrong, the oven beeps at me and doesn’t start. Sometimes it displays an error message on the little display.

This doesn’t sound very profound, and it isn’t really — until you consider all the things that I don’t do to use my microwave oven:

  • I limit myself to the front panel of the microwave. I don’t look inside the case. I don’t look at the listings of the code that tells the processor unit what to do. I don’t study the wiring diagram that’s pasted on the inside wall of the case.
  • I don’t rewrite any of the code or change anything inside the microwave to get it to work. The microwave oven that I use to make nachos is the exact same microwave that I used earlier to heat up chili dogs (nothing but health food at my house). And it will be the same microwave I use to heat up my Malt-O-Meal tomorrow (assuming it doesn’t break).
  • I don’t think about what might be going on inside my microwave oven in order to use it. Even if I designed microwaves for a living, I’m not likely to think about how it works when I make nachos before the big game.

These are not profound observations. Humans can think about only so much at any one time. We tend to reduce the number of things that we have to deal with by abstracting away all the little details. This allows us to work at the level of detail appropriate to the problem we’re trying to solve.

Note: In object-oriented (OO) terms, this level of detail is known as the level of abstraction.

When I’m working on nachos, I view my microwave oven as a black box. I don’t concern myself with what’s going on inside that box unless, of course, it breaks. Then I might take the top off and see if I can figure out what’s wrong with it; then I’m working at a different level of abstraction. I still don’t take the tops off the computer chips on the circuit board or try to take apart the individual components. (I’m not that crazy.)

As long as the microwave is heating food, I limit myself to the interface that it exposes to the outside world: the keypad and LCD display. It is very important that from this interface, there’s nothing that I can do that will cause the microwave to

  • Enter an inconsistent state and crash (causing me to have to reboot my microwave)
  • Worse, turn my nachos into a blackened, flaming mass
  • Worse yet, catch on fire and burn down the house

Procedural nachos

Suppose I were to ask my son to write an algorithm for making nachos using the same basic approach used for changing tires in Chapter 1. He would probably write something like, “Open a can of beans, grate some cheese, cut the jalapeños,” and so on. For the part about heating the nachos, he would write something similar to, “Cook in the oven until cheese is melted.”

That description is straightforward and complete, but it’s not how a procedural programmer would code a program to make nachos. Procedural programmers live in a world devoid of objects such as microwave ovens. They tend to worry about flowcharts (with their myriad functional paths). In a procedural solution, the flow of control would pass from my finger through the microwave’s front panel and on into the interior of the thing. Soon, the flow would be wiggling through complex logic paths concerned with how long to charge up some capacitor and whether it’s time to sound the “come and get it” tone.

In a world like this, it’s hard to think in terms of levels of abstraction. There are no objects, no abstractions behind which to hide inherent complexity.

Object-oriented nachos

In an object-oriented approach to making nachos, I would start by identifying the types of objects in the problem: chips, beans, cheese, and an oven. These are the nouns that I have to work with. That done, I would identify the verbs relevant to each object. Next, I would solve the problem using nothing but the nouns and verbs identified before. Finally, then, and only then, I would implement each of these objects in software.

remember.eps I identify the nouns and verbs relevant to tire-changing for you in Chapter 1. You’re left with the job of implementing the solution, using the nouns and verbs I gave you.

While I’m writing object-level code, I’m working (and thinking) at the level of abstraction of the basic objects. I need to think about making a useful oven, but I don’t have to think about the process of making nachos yet. After all, the designers of my microwave didn’t think about the specific problem of my making a snack. Rather, they set about the problem of designing and building a useful microwave oven.

After I have successfully coded and tested the objects I need, I can ratchet up to the next level of abstraction. I can start thinking at the nacho-making level, rather than at the microwave-making level. At this point, I can pretty much translate my son’s instructions directly into C++ code.

Classification and Microwave Ovens

Critical to the concept of abstraction is that of classification. If I were to ask my son, “What’s a microwave oven?” he would probably say, “It’s an oven that… .” If I then ask, “What’s an oven?” he might reply, “It’s a kitchen appliance that… .” I could keep asking this question, ratcheting myself up the abstraction ladder until I ended up with, “It’s a thing,” which is another way of saying, “It’s an object.”

My son understands that our particular microwave is an instance of the type of things called microwave ovens. In addition, he sees microwave ovens as just a special kind of oven, which is, in turn, a special type of kitchen appliance, and so on.

The technical way of saying all this is that our oven is an instance of the class microwave. The class microwave is a subclass of the class oven, and the class oven is a superclass of the class microwave.

Humans classify. Everything about our world is ordered into taxonomies. We do this to reduce the number of things that we have to remember. Consider, for example, the first time that you saw a hybrid car. The advertisement called it a “revolutionary automobile, unlike any car you’ve ever seen,” but you and I know that this just isn’t so. Sure, its propulsion system is different from conventional cars, but it’s still a car and as such does the same things that all cars do: convey you and your kin from one place to another. It has a steering wheel, seats, a motor, brakes, and so on. I bet I could even drive one without help.

I don’t have to clutter my limited storage with all the things that a hybrid card has in common with other cars. All I have to remember is that “a hybrid car is a car that …” and tack on those few things that are unique to a hybrid. Cars are a subclass of wheeled vehicles, of which there are other members, such as trucks and pickups. Maybe wheeled vehicles are a subclass of vehicles, which includes boats and planes. And on and on and on.

Why Build Objects This Way?

It may seem easier to design and build a microwave oven specifically for this one problem, rather than to build a separate, more generic oven-object. Suppose, for example, that I were to build a microwave to cook nachos and nachos only. I wouldn’t need to put a front panel on it, other than a START button. I always cook nachos the same amount of time. I could dispense with all that DEFROST and TEMP COOK nonsense. The microwave could be tiny. It would need to hold only one fat, little plate. Any more cubic feet of space would be completely wasted on nachos.

For that matter, suppose I just dispense with the concept of “microwave oven” altogether. All I really need is the guts of the oven. Then in the recipe, I can put the instructions to make it work: “Put nachos in the box. Connect the red wire to the black wire. Notice a slight hum. Don’t stand too close if you intend to have children.” Stuff like that.

Nevertheless, the procedural approach does have some problems:

  • Too complex. You don’t want the details of oven-building mixed in with the details of nacho-building. If you can’t define the objects and pull them out of the morass of details to deal with separately, you must deal with all the complexities of the problem at the same time.
  • Not flexible. If you need to replace the microwave oven with some other type of oven, you should be able to do so as long as the interface to the new oven is about the same as the old one. Without a simple and clearly delineated interface, it becomes impossible to cleanly remove one object type and replace it with another.
  • Not reusable. Ovens are used to make many different dishes. You don’t want to create a new oven each time you encounter a new recipe. Having solved a problem once, it would be nice to reuse the solution in future programs.

It does cost more to write a generic object. It would be cheaper to build a microwave made specifically for nachos. You could dispense with expensive timers, buttons, and the like that aren’t needed to make nachos. After you have used a generic object in more than one application, however, the costs of a slightly more expensive class more than outweigh the repeated costs of building cheaper, less flexible classes for every new application.

Self-Contained Classes

Now, it’s time to reflect on what you’ve learned. Here’s what happens in an object-oriented approach to programming:

  • The programmer identifies the classes necessary to solve the problem. (I knew right off that I was going to need an oven to make decent nachos.)
  • The programmer creates self-contained classes that fit the requirements of the problem and doesn’t worry about the details of the overall application.
  • The programmer writes the application using the classes just created without thinking about how they work internally.

An integral part of this programming model is that each class is responsible for itself. A class should be in a defined state at all times. It should not be possible to crash the program by calling a class with illegal data or with an illegal sequence of correct data.

Many of the features of C++ that are shown in subsequent chapters deal with giving the class the capability to protect itself from errant programs just waiting to trip it up.

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

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