Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Basic Concepts

What is an Abstract Class?

So far, we have considered classes that are fully implemented, but it is also possible to have classes that are only partially implemented. Such classes are known as abstract classes.

In a typical abstract class, one or more methods are declared but are not actually implemented. In other words, we specify their names, their parameter lists and their return types, but we do not supply a method body for any of them. These unimplemented methods are known as abstract methods. The intention is that subclasses will provide the missing implementations of these abstract methods.

Because an abstract class is incomplete, it is not possible to create an instance of such a class in a program. Attempting to do so will result in a compiler error. We are, however, allowed to create instances of concrete subclasses of that abstract class. A concrete subclass is a subclass that implements all of the abstract features of its superclass.

If you create a subclass of an abstract class but do not implement all of its abstract methods, then that subclass will also be abstract.

UML Representation

On UML class diagrams, abstract classes are often shown by rendering the name of the class, and the name of any abstract features, in an italic font.

It is also common to see class names labelled with the «abstract» stereotype1.

Here’s an example of a class that has a mixture of abstract and concrete features:

classDiagram
  class Vehicle {
    <<abstract>>
    fuelLevel: Int
    refuel(amount: Int)
    drive()*
  }

The Vehicle class exists to provide some state and functionality to instances of its subclasses, via the fuelLevel property and refuel() method. However, it also specifies an abstract method, drive().

A subclass of Vehicle that does not provide an implementation of the drive() method will also need to be labelled as «abstract».

classDiagram
  direction LR
  Vehicle <|-- WheeledVehicle
  WheeledVehicle <|-- Car
  note for WheeledVehicle "abstract, as it doesn't implement drive()"
  note for Car "concrete, because it implements drive()"
  class Vehicle {
    <<abstract>>
    fuelLevel: Int
    refuel(amount: Int)
    drive()*
  }
  class WheeledVehicle {
    <<abstract>>
    changeTyres()
  }
  class Car {
    drive()
  }

  1. Strictly speaking, this usage doesn’t conform fully to the rules of UML, but it is commonly seen, easy to understand, and is the only way of showing abstractness in some UML diagramming tools.