4.2.4 Abstract Classes and Methods


Placing classes in an inheritance hierarchy presumes that parent classes are more abstract and general than child classes, which are more concrete and specific. If your level of abstraction has gone up so far that a superclass in fact only acts as a template for all classes derived from it you speak of an abstract class. The Shape class in our example of the previous section could be considered as such. It collects geometrical objects like circles, squares, triangles, and so on, but instances will always be of the latter type and not a Shape instance. An example from the built-in Java library is the Number class that acts as a repository for classes like Integer and Double.

To declare an abstract class, use the keyword abstract before the class keyword in the class declaration:

public abstract class Shape {
 ...
}
Abstract classes cannot create instances, but for the rest they can contain anything a normal class can contain. If you now attempt to instantiate a Shape, the compiler will display an error message and refuse to compile your program. You can only instantiate objects like Circle and Square.

Java also provides a mechanism for defining a template of a method shared by subclasses of an abstract class: the abstract method. An abstract method, recognized by the abstract keyword before the methodname, has only a declaration and no method body. In our example of the Shape class you could define this class as follows:

public abstract class Shape {

  abstract double area();
  
  abstract double circumference();
}
The implementations of these methods will take place in the subclasses Circle, Square, and so on. But what is so nice about this is that you can now write Java code in which you call the area() method on a Shape object without knowing whether it is actually a Circle, Square, or another object. So, the following code snippet is perfectly legal in Java:
Shape[] shapes = new Shape[2];
shapes[0] = new Circle(0,0,1);
shapes[1] = new Rectangle(2,3,4);
for (int i=0; i<shapes.length; i++) {
   System.out.println( shapes[i].area() );
}
It is in an abstract class not unusual to define static variables and methods because these can be referred to via the class name. For example, you could define the abstract Shape class as follows:
public abstract class Shape {

  abstract double area();
  
  abstract double circumference();

  private static double maxSize = 100; // maximal size

  public static void setMaxSize(double size) {
    maxSize = size;
  }
}
One step further in the level of abstraction is the use of an interface, in which only the signature of methods is defined and no implementations are given.