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()andarea()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
Shapeobject without knowing the specific type, confident thatdraw()andarea()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:
Shapeinherits fromABC— this marks it as abstract.@abstractmethodmarksarea()anddraw()as abstract — they have no body (justpass).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.