5. Abstract Classes

Whenever a Rectangle, Oval, or RoundRect object has to draw itself, it is the Redraw() method in the appropriate class that is executed. This leaves open the question, What does the Redraw() method in the Shape class do? How should it be defined?

The answer may be surprising: We should leave it blank! The fact is that the class Shape represents the abstract idea of a shape, and there is no way to draw such a thing. Only particular, concrete shapes like rectangles and ovals can be drawn. So, why should there even be a redraw() method in the Shape class? Well, it has to be there, or it would be illegal to call it in the SetColor() method of the Shape class, and it would be illegal to write "oneShape.Redraw();", where oneShape is a variable of type Shape. The compiler would complain that oneShape is a variable of type Shape and there's no Redraw() method in the Shape class.

Nevertheless the version of Redraw() in the Shape class will never be called. In fact, if you think about it, there can never be any reason to construct an actual object of type Shape! You can have variables of type Shape, but the objects they refer to will always belong to one of the subclasses of Shape. We say that Shape is an abstract class. An abstract class is one that is not used to construct objects, but only as a basis for making subclasses. An abstract class exists only to express the common properties of all its subclasses.

Similarly, we say that the Redraw() method in class Shape is an abstract method, since it is never meant to be called. In fact, there is nothing for it to do -- any actual redrawing is done by Redraw() methods in the subclasses of Shape. The Redraw() method in Shape has to be there. But it is there only to tell the computer that all Shapes understand the redraw message. As an abstract method, it exists merely to specify the common interface of all the actual, concrete versions of Redraw() in the subclasses of Shape. There is no reason for the abstract Redraw() in class Shape to contain any code at all.

Shape and its Redraw() method are semantically abstract. You can also tell the computer, syntactically, that they are abstract by adding the modifier "abstract" to their definitions. For an abstract method, the block of code that gives the implementation of an ordinary method is replaced by a semicolon. An implementation must be provided for the abstract method in any concrete subclass of the abstract class. Here's what the Shape class would look like as an abstract class:

       abstract class Shape {
       
           Color color;   // color of shape. 
                                     
           public void SetColor(Color newColor) {
                 // method to change the color of the shape
              color = newColor; // change value of instance variable
              Redraw(); // redraw shape, which will appear in new color
           }
           
           public abstract void Redraw();
                 // abstract method -- must be defined in 
                 // concrete subclasses

           . . .          // more instance variables and methods

       } // end of class Shape

Once you have done this, it becomes illegal to try to create actual objects of type Shape, and the computer will report an error if you try to do so.