Abstract base classes are special types of classes in Python. They allow a programmer to define a base class as a template for other classes to inherit from. The difference between abstract base classes and normal classes in Python is that with abstract base classes you don’t want consumers of your base class to be able to create instances of the base class itself. The abstract base class servers only as a blueprint. Subclasses are the means of providing a concrete implementation of that blueprint. In addition to this, you can enforce the constraint that there are certain methods in the base class that subclasses have to implement.
Simple Class With Inheritance
class Vehicle:
def __init__(self):
super().__init__()
def go_forward(self):
print('Driving forward.')
class Car(Vehicle):
def __init__(self):
super().__init__()
class Truck(Vehicle):
def __init__(self):
super().__init__()
vehicle1 = Vehicle()
car1 = Car()
car1.go_forward()
truck1 = Truck()
truck1.go_forward()
Driving forward. Driving forward.
This code above is a simple Vehicle class and two additional classes, Car and Truck. We want this program to be extensible so that new car or truck types can be added. We can certainly create a program like this without using an abstract base class. In fact, the code above seems to work. When we call the method that was inherited on the car and truck objects, they both drive forward. Notice that we also instantiated a Vehicle object. We don’t really need that since the Car and Truck can do all they need to do without having an instance of Vehicle created. We can change this code up to make use of an abstract base class to accomplish a few things.
Adding Abstract Base Class
To make use of an abstract base class in Python you need to import ABC and abstractmethod as we see here.
from abc import ABC, abstractmethod
Inheriting From Abc Indicates That This Is An Abstract Base Class
The Vehicle class here has a type of <class ‘abc.ABCMeta’>.
from abc import ABC, abstractmethod
class Vehicle(ABC):
def __init__(self):
super().__init__()
Declaring A Method As Abstract Requires A Subclass To Implement It
from abc import ABC, abstractmethod
class Vehicle(ABC):
def __init__(self):
super().__init__()
@abstractmethod
def go_forward(self):
pass
The syntax above is a bit special. We can see the @abstractmethod decorator which tells Python, this method needs to be implemented by any subclass that inherits from the abstract base class.
Abstract Base Class Can Not Be Instantiated
Since Vehicle has now inherited from ABC, it can no longer be instantiated. If we try, Python will throw an error.
vehicle1 = Vehicle()
Traceback (most recent call last): File "C:/python/justhacking/abc.py", line 38, in <module> vehicle1 = Vehicle() TypeError: Can't instantiate abstract class Vehicle with abstract methods go_forward
Adding A Subclass
Let’s create a Car class example that now inherits from Vehicle. Since we have put some rules in place on the Vehicle class using the ABC module, you’ll see that Python outputs an error if we don’t create the Subclass with the needed attributes or methods.
class Car(Vehicle):
pass
car1 = Car()
Traceback (most recent call last): File "C:/python/justhacking/abc.py", line 38, in <module> car1 = Car(True) TypeError: Can't instantiate abstract class Car with abstract methods go_forward
Python is now enforcing the fact that if we want to have a Subclass of Vehicle, it must implement the go_forward() method. Let’s give it another shot.
class Car(Vehicle):
def __init__(self, press_accelerator):
super().__init__()
self.press_accelerator = press_accelerator
def go_forward(self):
if self.press_accelerator:
print('Driving forward')
else:
print('Press the accelerator to drive forward')
car1 = Car(True)
car1.go_forward()
Driving forward
A Second Subclass
We can create a different subclass of Truck that also inherits from the Vehicle abstract base class.
from abc import ABC, abstractmethod
class Vehicle(ABC):
def __init__(self):
super().__init__()
@abstractmethod
def go_forward(self):
pass
class Truck(Vehicle):
def __init__(self, press_accelerator):
super().__init__()
self.press_accelerator = press_accelerator
def go_forward(self):
if self.press_accelerator:
print('Driving forward')
else:
print('Press the accelerator to drive forward')
truck1 = Truck(False)
truck1.go_forward()
truck2 = Truck(True)
truck2.go_forward()
Press the accelerator to drive forward Driving forward
Abstract base classes can be a very useful tool for enforcing a set of constraints among the consumers of any given class. Abstract base classes are worth taking the time to experiment with to understand their potential benefits.
- Abstract classes are classes that are meant to be inherited but avoid implementing specific methods, leaving behind only method signatures that subclasses must implement.
- Abstract classes are useful for defining and enforcing class abstractions at a high level, similar to the concept of interfaces in typed languages, without the need for method implementation.
- With the abc module we can prevent child classes from being instantiated when they fail to override abstract class methods of their parents and ancestors.