Abstract Classes in Python
In my post Classes in Python I have an example of creating a class named Car and instantiating this class. In reality you would rarely do something like this, but rather use this class as a base class in order to create subclasses. Subclasses are classes that extend the base class and inherit all functionality from it. We can go one step further and define “Car” as an abstract class.
What is an abstract class? An abstract class is a class that defines some methods and properties, but ususally does not define any implementation. This has some consequences. First, you cannot instantiate this class. Second, subclasses, that is classes that inherit from this class, must provide implementation for all methods and properties defined in the abstract class with @abstractmethod decorator. Because python does not provide builtin functionality for abstract classes we have to import module abc (abstract base class).
from abc import ABC, abstractmethod
class Car(ABC):
@abstractmethod
def start(self):
pass
@abstractmethod
def stop(self):
pass
class VWCar(Car):
def start(self):
print("VW car started")
def stop(self):
print("VW car stopped")
class ToyotaCar(Car):
def start(self):
print("Toyota car started")
def stop(self):
print("Toyota car stopped")
car1 = VWCar()
car1.start()
car1.stop()
car2 = ToyotaCar()
car2.start()
car2.stop()
the output is
VW car started
VW car stopped
Toyota car started
Toyota car stopped
Please note that I cannot instantiate Car class. If I try to do this, I will get an error. I will make my code more modular by splitting each class in its own file car.py
from abc import ABC, abstractmethod
class Car(ABC):
@abstractmethod
def start(self):
pass
@abstractmethod
def stop(self):
pass
toyotacar.py
from .car import Car
class ToyotaCar(Car):
def start(self):
print("Toyota car started")
def stop(self):
print("Toyota car stopped")
vwcar.py
from .car import Car
class VWCar(Car):
def start(self):
print("VW car started")
def stop(self):
print("VW car stopped")
nullcar.py
from .car import Car
class NullCar(Car):
def __init__(self, carmodel):
self.carmodel = carmodel
def start(self):
print("unknown car {}".format(self.carmodel))
def stop(self):
pass
main.py
from toyotacar import ToyotaCar
from vwcar import VWCar
from nullcar import NullCar
def getcar(carmodel):
if carmodel == 'VW':
return VWCar()
elif carmodel == "Toyota":
return ToyotaCar()
else:
return NullCar(carmodel)
for carmodel in ["VW","Toyota","Chevy"]:
car = getcar(carmodel)
car.start()
car.stop()
this design in my my main.py with the elif statements is not good, because I have to modify it each time I create another car. In the next post we will use another class called carfactory which will create the instance of the car for us and make our code more maintainable.