An abstract class is a class that cannot be instantiated directly and is designed solely to be inherited by subclasses. It defines a common interface — including abstract methods that every subclass must implement — guaranteeing that all objects in a class hierarchy share a consistent set of behaviours, even if those behaviours are implemented differently in each subclass.

What problem does an abstract class solve?

Imagine writing a drawing program with classes for Circle, Rectangle, and Triangle. All three shapes can be drawn and can calculate their area, but the formula is different for each. You want to guarantee that any shape object in your program definitely has a draw() and area() method — but there is no sensible "generic shape" object you could ever create directly.

An abstract class called Shape solves this:

  • It declares draw() and area() as abstract methods — methods with no implementation, just a signature.
  • Any concrete subclass (Circle, Rectangle, Triangle) must provide its own implementation or Python refuses to create objects from it.
  • Code elsewhere in the program can work with any Shape object without knowing the specific type, confident that draw() and area() will always exist.

How do you define an abstract class in Python?

Python uses the abc (Abstract Base Classes) module. Import ABC and abstractmethod, inherit from ABC, and decorate abstract methods:

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def draw(self):
        pass
    
    def describe(self):           # concrete method — has an implementation
        return "I am a shape."

Key points:

  • Shape inherits from ABC — this marks it as abstract.
  • @abstractmethod marks area() and draw() as abstract — they have no body (just pass).
  • describe() is a concrete method — it has a real implementation that subclasses inherit as-is.

What happens if a subclass does not implement all abstract methods?

Attempting to instantiate an abstract class, or a subclass that still has unimplemented abstract methods, raises a TypeError:

# This raises TypeError — cannot instantiate abstract class
s = Shape()

class IncompleteShape(Shape):
    def area(self):          # implements area but NOT draw
        return 0

# This also raises TypeError — draw() is still abstract
i = IncompleteShape()

Python's error message names the missing method, making it easy to see what still needs implementing.

A complete worked example

from abc import ABC, abstractmethod
import math

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Circle(Shape):
    def __init__(self, radius):
        self.__radius = radius
    
    def area(self):
        return math.pi * self.__radius ** 2

class Rectangle(Shape):
    def __init__(self, width, height):
        self.__width = width
        self.__height = height
    
    def area(self):
        return self.__width * self.__height

shapes = [Circle(5), Rectangle(4, 6)]
for shape in shapes:
    print(f"{type(shape).__name__}: area = {shape.area():.2f}")
# Circle: area = 78.54
# Rectangle: area = 24.00

The loop calls area() on every shape without knowing the specific type — the abstract class guarantees the method exists, and each subclass provides the correct formula.

What is an interface, and how does it differ from an abstract class?

In languages like Java and C#, an interface is a structure that declares method signatures with no implementation at all — it is a pure contract. An abstract class in those languages can have some concrete methods and some abstract methods.

Feature Abstract class Interface (Java/C#)
Can have concrete methods? Yes No (in Java)
Can have attributes? Yes No (only constants)
A class can inherit from One (single inheritance) Many (a class implements multiple interfaces)
Purpose Partial template + contract Pure contract

Python does not have a separate interface keyword. Instead, a Python class that inherits from ABC and has only @abstractmethod methods functions as an interface. The abc module's register() method also allows existing classes to be registered as "virtual subclasses" of an ABC without inheriting from it directly, but this is beyond GCSE scope.

Frequently asked questions

When should I use an abstract class rather than a regular parent class?

Use an abstract class when the parent concept is meaningful for grouping (e.g., Shape, Vehicle, Account) but instantiating the parent directly would be nonsensical (you would never need just "a shape" — only a Circle or a Rectangle). If the parent class represents a real, usable object in its own right, make it concrete.

Do I need to use abstract classes in my GCSE project?

Using abstract classes in a GCSE programming project demonstrates a sophisticated understanding of OOP design and can earn marks for design quality. They are not compulsory, but they show you have thought carefully about the class hierarchy. Even without the ABC module, you can write a parent class with methods that raise NotImplementedError as a lightweight alternative.

What is the difference between an abstract method and a method that does nothing?

An abstract method (decorated with @abstractmethod) forces every concrete subclass to provide its own implementation — Python enforces this at class definition time. A method that does nothing (return None or just pass) is a valid implementation; subclasses will inherit it silently and may or may not override it. Abstract methods prevent the common mistake of forgetting to implement required behaviour.

Can an abstract class have a constructor?

Yes. An abstract class can have an __init__ method that initialises shared attributes. Concrete subclasses can call it using super().__init__(...). The restriction is only that the abstract class itself cannot be instantiated with Shape() — but when a subclass is instantiated, Python runs the full chain of constructors including the parent's.


Work through OOP design from abstract classes to full implementations with Professor Turing at aitutors.me.