Abstract base classes in Python
In the previous section, we redesigned the code using the OOP approach. We also demonstrated the use of inheritance by defining a superclass GameUnit
, and inheriting from it to create the Knight
and OrcRider
subclasses. As the last topic in this chapter, let's talk about using abstract base classes in Python.
Tip
This section is intended to provide a basic understanding of ABCs in Python. The discussion here is far from being comprehensive but will be just enough to implement an ABC in our application code. For further reading, check out the Python documentation at https://docs.python.org/3/library/abc.html.
If you are familiar with OOP languages such as Java or C++, you probably already know the concept of an ABC.
A base class is a parent class from which other classes can be derived. Similarly, you can have an abstract base class and create other classes that inherit this class. So, where is the difference? One of the major differences is that an ABC can't be instantiated. But that is not the only difference. An ABC forces the derived classes to implement specific methods defined within that class. This much knowledge about an ABC should be good enough to work through the examples in this book. For more details, see the aforementioned Python documentation link. Let's review a simple example that shows how to implement an abstract base class in Python and how it differs from an ordinary base class. The abc
module provides the necessary infrastructure. The following code snippet compares the implementation of an ABC to an ordinary base class:
The class on the left, AbstractGameUnit
,
is the abstract base class, whereas the GameUnit
class on the right is an ordinary base class. The three differences in the ABC implementation are marked with numbers, as shown in the preceding screenshot.
- The argument
metaclass=ABCMeta
is used to defineAbstractGameUnit
as an ABC. - The
ABCMeta
is a metaclass to define the abstract base class. It is a broad discussion topic, but the simplified meaning of a metaclass is as follows: to create an object, we use a class. Likewise, imagine a metaclass as one used to create a class. - A Python decorator provides a simple way to dynamically alter the functionality of a method, a class, or a function. This is a special Python syntax that starts with an @ symbol followed by the decorator name. A decorator is placed directly above the method definition.
- The
@abstractmethod
is a decorator that makes the method defined on the next line an abstract method. - The abstract method is the one that the ABC requires all the subclasses to implement. In this case,
AbstractGameUnit
requires itsKnight
subclass to implement theinfo()
method. If the subclass does not implement this method, Python simply doesn't instantiate that subclass and will throwTypeError
. You can try this by removing theKnight.info
method and running the code. - There is no such restriction if the
Knight
class inherits from an ordinary base class, such asGameUnit
.
Tip
The code illustrated here is for Python version 3.5. For version 2.7, the syntax is different. Refer to the ch01_ex03_AbstractBaseClass.py
file in the Python2 directory of the supporting material for an equivalent example.
Exercise
In the ch01_ex03.py
file, you will see some comments. These are intentionally kept to give you an opportunity to improve portions of the code. There is plenty of room for improvement in this code. See if you can rewrite portions of the code to make it more robust. If you prefer a well-defined problem, here is one:
The Knight
and OrcRider
classes inherit from the GameUnit
superclass. This exercise is about converting GameUnit
to AbstractGameUnit
, an abstract base class. Here is a cheat sheet for you; the skeleton code shown in the following figure is with the Python 3.5 syntax.
Refer to the ch01_ex03_AbstractBaseClass.py
file:
Tip
Note that for Python 2.7, there is a separate version of this code. Refer to the src_ch1_Python2
directory in the supporting code bundle.