An abstract class is a class that has methods with no implementation. Abstract class is a blueprint contract for other classes inherit from it. The abstract class cannot be instantiated, and its descendants also cannot be instantiated unless they provide implementation for methods marked by the abstractmethod decorator. The Abstract Methods in an abstract class is like a contract agreement that it must be build with certain arguments within any child classes inherited from the abstract class.
Abstract method by itself is just declaration of the name of the methods without implementation. This technique is very useful to provide common Interface for various implementation of the methods. Using Abstract class, you create the design and specification on the code that must be implemented later.
In this tutorial, you will learn about:
Several ways to define an abstract class:
The abstract methods in the abstract class does not need to be implemented. If it implemented, it would become a template for the children of the abstract class.
To implement the abstract class into a concrete class, it is done by inherit from the abstract class. The abstract methods must be implemented in the concrete classes.
from abc import ABCMeta, abstractmethod
class AbstractClass(object):
# the metaclass attribute is used to register an abstract class
__metaclass__ = ABCMeta
# this method must be build in any of the children of the Abstract class
@abstractmethod
def method(self):
pass
# Another way to register abstract class is simply by setting metaclass=ABCMeta
class AbstractClass(metaclass=ABCMeta):
@abstractmethod
def method(self):
pass
from abc import ABC, abstractmethod
# Another way to register abstract class is simply by inherit from ABC
class AbstractClass(ABC):
# this method must be build in any of the children of the Abstract class
@abstractmethod
def method(self):
pass
In the code below, class Shape is not an abstract class. Rectangle class just inherit from Shape class but even if we did not implement area() method in Rectangle, there is no complain.
class Shape():
def area(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
rectangleD = Rectangle(width=3, height=5)
To create abstract class in Python, you need to import the abstractmethod decorator and module ABC from built-in Python module Abstract Base classes (ABC).
ABC works by decorating methods of the base class as abstract and then registering concrete classes as implementations of the abstract base.
from abc import ABC, abstractmethod
# Shape is now an Abstract class
class Shape(ABC):
# area method must be build in any of the children of Shape class
@abstractmethod
def area(self):
pass
# Rectangle is now a concrete class of Shape
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
# overriding abstract method
def area(self):
return self.width * self.height
rectangleD = Rectangle(width=3, height=5)
print('Area rectangle D is ', rectangleD.area())
Area rectangle D is 15
What happen if the child class did not build the method from the abstract class? Because we did not build according to the contract in the Abstract class, it would generate Exception error. This is error is by design. We deliberately make this error because it is useful to remind us that we must provide the method that already specified in the Abstract class.
Thus, the abstract method in the abstract class serves as a contract interface that must be implemented in a certain way. This is how we enforced the interface.
from abc import ABC, abstractmethod
# Shape is now an Abstract class
class Shape(ABC):
# area() must be build later in any of the children of Shape class
@abstractmethod
def area(self):
pass
# Rectangle is now concrete class of Shape
# but we did not build according to the contract
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
# this would generate Exception
try:
rectangleD = Rectangle(width=3, height=5)
except Exception as e:
print(e)
Can't instantiate abstract class Rectangle with abstract method area
An Interface is a description of all functions that an object must have in order to be that object. For example, we expect a lightbulb object must have turnOn and turnOff methods. We expect a shape objects such as circle, square and rectangle would have draw method
In Python, we can create another class interface such as IShape and These methods are defined but not implemented. We then provide implementations for the declared methods.
Notice that we deliberately put raise NotImplementedError to make by designed error such that if the programmer forget to implement, it would generate error
class iShape():
def draw(self):
raise NotImplementedError
class circle(iShape):
def draw(self):
pass
class square(iShape):
def draw(self):
pass
class rectangle(iShape):
def draw(self):
pass
The interface segregation principle (ISP) states that no code should be forced to depend on methods it does not use. This principle would suggest us to create highly specialized interfaces and don't force the client to depend on unused interfaces. We splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them.
For example, you have a class Auto with radiokit methods for all cars. If we inherit from an interface, then all methods implemented in it must be described in the descendant class. As a result, classes may receive unnecessary methods. To solve this problem, we separate the interfaces.