In our previous article about polymorphism, we gave an example of a Shape class inherited by three subclasses, Rectangle, Triangle, and Circle. With polymorphism, a variable of type Shape can reference an object of any of the 3 subclasses.

However if you look at the example closely, the area() method of the Shape class (shown below) actually returns 0, because shape is a very abstract concept, and we can’t actually compute the area, so we just wrote a placeholder method.

class Shape {
    public double area() {
        return 0;
    }
}

This is where the idea of abstract class comes in. An abstract class in Java is a class that cannot be instantiated, but allows programmer to define methods for subclasses. Let’s see how this works.

Defining Abstract Class

An abstract class is marked with the abstract modifier, as shown below.

abstract class Shape {
    public abstract double area();
}

Abstract classes usually contain abstract method, like area() above, because that is the purpose of an abstract class.

Also an abstract class cannot be a final class. The reason is that a final class cannot be inherited, but an abstract has to be inherited or else it cannot be instantiated and useless.

Extending Abstract Class

A subclass of an abstract class must override all of the parent’s abstract methods, or it must be declared abstract. For example, the ColorShape class must be abstract because it does not override the area() method.

abstract class ColorShape extends Shape {
    protected String color;
    public String getColor() {
        return color;
    }
}

Polymorphism with Abstract Class

Abstract classes go hand-in-hand with polymorphism. As shown the previous example, we can define a very high-level concept as an abstract class, with abstract methods. We let the concrete subclasses to write the logic for these methods.

The good thing about this approach is that we do not accidentally execute some placeholder method, and Java will pick the correct method to execute based on the concrete object type.