Increasing Reusability - Shape class hierarchy Print E-mail
Wednesday, 31 January 2001 09:24
Article Index
Increasing Reusability
Classification and inheritance
Shape class hierarchy
Multiple inheritance
All Pages

The Shape Class Hierarchy

Classification makes it easy to reuse code in OOP. To demonstrate this with C++, let’s consider our shape hierarchy. Since a shape is so simple and we have no idea what a particular shape might look like (remember, a point or even a line is a shape), all we might want for now is for a shape to be able to create itself. So the only member that we give the class Shape is the method create()In most OOPLs, including C++, a special kind of method called a constructor is used to create objects. However, I’ll keep things simple here by ignoring constructors. This introduction focuses on OOP concepts, not on OOPL syntax. The sample OO program, though, will use constructors and explain a little bit how they’re used.. (Note the open-and-close parentheses “()” that identify a method, distinguishing it from a data member.) Our simple implementation of create will simply print out “New Shape created.”


class Shape {
public: 
void create(void) {
cout << "New Shape created.";
// "cout <<" in C++ means, print to console output
// "void" in C++ means that no data type is returned
}
}

When we create a Polygon (a closed shape whose sides are straight lines), we have a better idea what this shape would look like and what we would want to do with it. First and foremost, we define a Polygon as a Shape. This apparently trivial step automatically gives us the create() method without having to redefine it. Because a Polygon is a Shape, it inherits all of Shape’s members (in this case just one method). As we go further down the hierarchy, you’ll begin to appreciate better the power of inheritance. For now, let’s give Polygon a numSides data member, and for some more functionality we’ll give it print() and listProperties() methods.


class Polygon: public Shape {  // Define Polygon as a subclass of Shape
public: // "public" is part of the C++ information hiding schema
int numSides = 0;

void print(void) {
// insert printing code here
}

void listProperties(void) {
cout << "Polygon: numSides = " << numSides;
}
}

Notice that we don’t redefine the create() method in Polygon; it automatically inherits it from Shape.

Next we create a Quadrilateral (a polygon with four sides). In a traditional programming language, we would probably cut and paste the Polygon code to take advantage of the members we’ve already created. But in OOP, we simply define a Quadrilateral as a Polygon, and voila, we automatically inherit all its members.

There is one slight problem, though. We want to enforce the rule that a Quadrilateral has four and only four sides. The simplest way to do this in OOP is to rewrite the create() function for our purposes.


class Quadrilateral: public Polygon {
public:
int sideA, sideB, sideC, sideD;

void create(void) { // overriding the create() in Shape
numSides = 4;
cout << "New Quadrilateral created. ";
}

void setSides( int a, int b, int c, int d ) {
sideA = a;
sideB = b;
sideC = c;
sideD = d;
}
}

When we rewrite the create() method, then whenever this method is called for a Quadrilateral, its own create() will be called rather than Shape’s. This is an important OOPL feature: if the implementation in a superclass of a method or even a data member doesn’t meet our needs, we can always override it in this way. 

Quadrilateral adds its own special members: data members to represent its four sides, and the method setSides() to set them. Notice that Quadrilateral automatically inherits Polygon’s print() and listProperties() methods. As long as it doesn’t mention these methods, then they’re inherited without changes. Quadrilateral also inherits the numSides data member; that’s why it could assign it the value 4 in the create() method.

Now, what if a programmer creates a Quadrilateral object and wants to set numSides to 6? The way the class is defined, there’s no way to do that. While I won’t get into the details of how different OOPLs implement information hiding, I will note here that since a Quadrilateral conceptually will always have four sides, the designer of the class doesn’t even give the programmer the option to accidentally change that value. Thus the very chance of that bug is easily eliminated. This is one of the advantages of programming with encapsulated objects.

So far, our object-oriented design has only saved us a few lines of code, but when you write programs in the order of thousands of lines and more, object-oriented design can easily cut your code in half. Not only does this save time, but it also saves you the headache of slugging through all that complex code you have to debug, which translates to exponential time and effort savings.



Last Updated on Tuesday, 28 October 2008 14:51