The Final Answer: What Is OOP?


How is that for a bold headline? Really, I’m being a bit sarcastic, because no matter how I (or you, or anybody else) define object-oriented programming, somebody will disagree. I once was having a conversation with somebody about Borland Delphi, and that person had never so much as even seen Delphi, and I referred to it as “object-oriented.” This man looked me in the eyes and said with full authority, “No, it’s not.”

And by many regards, he was correct. If you expect OOP to live up to the original notions of Smalltalk (hailed by many as the standard on OOP), then no, Delphi isn’t object-oriented.

Hogwash. Here’s how I personally define OOP:

Object-oriented means you can encapsulate data and functions into classes.

Now most better OOP languages also allow inheritance: You can take one class and from it derive another class. And with inheritance comes the fundamental requirement of polymorphism, meaning that you can treat an instance of a derived class as an instance of a base class.

I’m assuming you’ve experienced enough OOP to understand what I’m talking about here, but this notion of polymorphism does sometimes cause some confusion. So let me just show you a quick example. Suppose you have two classes, Base and Derived, defined like so:

 class Base {  public:      string name;  }; 

 class Derived : public Base {  public:      int length;  }; 

You can see that Derived is derived from Base. Now suppose you have a function that takes an instance of Base:

 void Objectorator(Base &obj) {      cout << obj.name << endl;  } 

Thanks to the principle of polymorphism, you can pass to this function an instance of Base, or an instance of any class derived from Base. Here’s a complete gcc program demonstrating this:

 #include <iostream>  #include <string>  using namespace std;  class Base {  public:      string name;  };  class Derived : public Base {  public:      int length;  };  void Objectorator(Base &obj) {      cout << obj.name << endl;  }  int main() {      Derived inst;      inst.length = 10;      inst.name = "me";      Objectorator(inst);  } 

Notice in the main that I’m creating an instance of Derived, setting its two members (length, which is its own, and name, which is derived from Base). And notice how I then call Objectorator, passing this instance of Derived, even though Objectorator is expecting an instance of Base.

Internally, the way most C++ compilers handle inheritance to accommodate polymorphism is that they group together the data members starting with the base class. For example, if a base class has three integer members A, B, and C, and from that base class you derive a class with three more integer members D, E, and F, then the internal structure of the derived class is six integers in this order: A, B, C, D, E, F. But if you look at this structure and are expecting to see an instance of the base class, then you will see an instance of the base class: You will see A, B, C and stop looking beyond that, not knowing (and not caring) that the data that follows is still a part of the structure. Thus, in the preceding code sample, the function Objectorator will receive a structure containing a single data member, name. When I pass an instance of Derived to this function, the function doesn’t know that really Derived has additional data beyond its Base part. The function simply sees the first data element—a string—and accesses that string. Thus, the function thinks it has an instance of Base.

I like to envision polymorphism visually. In Figure 11.1, I demonstrate how I view polymorphism for a base class with members A, B, and C and a derived class with members A, B, C, D, E, and F. In this figure, you can see that the class Derived effectively contains an instance of the class Base. And that instance of Base is at the beginning, meaning the address of the instance of Base is the same as the address of the instance of Derived. And that means you can cast an instance of Derived to an instance of Base. (However, the C++ standard discourages us from doing a direct cast as in (Base)inst, even though that works. Instead, we’re encouraged to use the dynamic_ cast<Base&>(inst). But really, in general, you should have no reason to cast an instance of a derived class to a base class, because the compiler automatically casts in such cases, as I demonstrated by passing an instance of Derived to a function expecting an instance of Base.)

click to expand
Figure 11.1: Polymorphism in C++ is possible due to the overlapping structures.

Figure 11.1 and my explanation of the figure show how C++ implements inheritance and polymorphism. Other languages use similar approaches.

Now back to our story. In the early 1990s, when C++ was new, people would argue over whether it was truly object-oriented. The self-proclaimed gurus would say it wasn’t, and some people even came up with their own terms and definitions to work around suggesting that C++ and other languages were object-oriented. One such term was object-based. I remember being told, “Well, no, actually C++ and Delphi are both object-based.” Once again I say: Hogwash. Both of these languages support encapsulation, inheritance, and polymorphism. Thus, they are object-oriented. End of story. Now leave me alone.

REAL WORLD SCENARIO: That Darn Remote! (And Why Does It Have an Eject Button?)

start example

I’m sure you figured it was only a matter of time in this book before I talked about remotes. While object-oriented may have been the buzzword of the late twentieth century, the remote was probably the ubiquitous object of the twentieth century.

I remember sometime around maybe 1988 or 1989, a friend of mine bought a massive stereo system, which, of course, came with a remote. And my friend showed off this really “cool feature” of the stereo: When you used the remote to change the volume, the volume knob on the stereo itself would turn. Ooooh. I wonder how many engineers it took to design that. That knob was more than a basic potentiometer; it was motorized. I do have to wonder, however, what would happen if you used the remote to turn up the volume, while somebody stood by the stereo itself and manually forced the motorized knob in the opposite direction. Would the stereo explode? Or maybe you would discover some secret mode where the stereo could emit frequencies previously unheard by human ears?

While in college, I took several electrical engineering courses. I was talking about that once, and a friend of mine mentioned that her brother, who was in his early twenties, knew a lot about electronics. She then added, “I know he does because he bought this HUGE stereo system and managed to hook the whole thing up all by himself.”

And how much you wanna bet that the stereo he hooked up (all by himself) has a Magical Rotating Volume Knob? Do you see what is happening here? We have stereos that are nearly impossible to use by most people, yet are filled with wow-cool factors. Consider the remote: How many buttons can you possibly squeeze into such a little remote, and how many colors of ink can you have on it? But do you know what each and every button does on each remote you have in your house? If I told you, “Quick, program the TV so when The X Files comes on tonight, the TV will start up and I can watch it, but the VCR will also be recording it,” would you know what to do?

The stereo industry has been plagued by the problem of adding so many bells and whistles for the coolness factor without actually doing much in the way of usability studies. If we computer programmers aren’t sure what all the buttons do without having to study the manual, imagine the mere mortals trying to figure them out. (Yes, we’re not mortal; I admit it.)

But answer me this: Why does the VCR remote have an Eject button on it? The remote has come to symbolize the laziness of humans, but that one makes no sense: So you can eject the tape, but until we invent a robot that will go over and remove the tape and insert a different one, what’s the point?

Don’t let your designs get out of control. Focus on usability.

end example




Designing Highly Useable Software
Designing Highly Useable Software
ISBN: 0782143016
EAN: 2147483647
Year: 2003
Pages: 114

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net