In practice, code in abstract classes typically contains more than just the pass
statement. Abstract classes serve as blueprints for derived classes, providing common attributes, methods, or properties that are meant to be implemented or extended by their subclasses.
While the abstract methods are indeed declared using @abstractmethod
decorators with a pass
statement in their implementation, the abstract class can have other concrete methods or properties that may provide default behavior or functionality shared among its subclasses.
Let's take the Shape
example from earlier and expand it to include a concrete method in the abstract class:
from abc import ABC, abstractmethod, abstractproperty
class Shape(ABC):
@abstractmethod
def calculate_area(self):
pass
@abstractproperty
def perimeter(self):
pass
def display_info(self):
print(f"This is a {type(self).__name__} with area: {self.calculate_area()} and perimeter: {self.perimeter}.")
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def calculate_area(self):
return 3.14 * self.radius ** 2
@property
def perimeter(self):
return 2 * 3.14 * self.radius
class Square(Shape):
def __init__(self, side):
self.side = side
def calculate_area(self):
return self.side ** 2
@property
def perimeter(self):
return 4 * self.side
In this example, Shape
now includes a concrete method display_info()
that provides default behavior for displaying information about a shape. It does not have the @abstractmethod
decorator, so it doesn't need a pass
statement in its implementation. However, it relies on the abstract methods calculate_area()
and perimeter()
, which are implemented in the Circle
and Square
subclasses.
In summary, while abstract classes often have abstract methods with pass
statements, they can also have concrete methods or properties that provide default behaviors or functionalities shared by their subclasses. This combination of abstract and concrete methods in abstract classes helps structure the code and encourage code reusability.
Using only "pass" in abstract classes for the implementation of abstract methods (i.e., using @abstractmethod
) is a recommended practice for several reasons:
abc
module ensures that any attempt to create an instance of the abstract class without implementing the abstract method results in an error, enforcing the requirement for subclasses to provide the implementation.In summary, using only "pass" in abstract classes for the implementation of abstract methods is a best practice that promotes clarity, safety, and flexibility. It enables clear separation of concerns and encourages code reusability and extensibility, leading to a well-designed and maintainable codebase.