Python tutorials > Object-Oriented Programming (OOP) > Inheritance > What are abstract base classes?

What are abstract base classes?

Abstract Base Classes (ABCs) are classes that cannot be instantiated directly. They serve as blueprints for other classes, defining a set of methods that subclasses must implement. ABCs enforce a specific interface, ensuring that derived classes adhere to a contract. This is a powerful tool for code organization and maintainability, especially in large projects.

In Python, ABCs are defined using the abc module. The ABCMeta metaclass is used to create abstract classes, and the @abstractmethod decorator is used to declare abstract methods.

Basic Example of an Abstract Base Class

This example demonstrates a simple abstract base class called Shape. It defines two abstract methods: area and perimeter. Any class that inherits from Shape must implement these methods. If a subclass fails to implement any of the abstract methods, attempting to instantiate that subclass will raise a TypeError.

The Square class inherits from Shape and provides concrete implementations for area and perimeter.

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

class Square(Shape):
    def __init__(self, side):
        self.side = side

    def area(self):
        return self.side * self.side

    def perimeter(self):
        return 4 * self.side

# Attempting to instantiate Shape directly will raise a TypeError
# shape = Shape()

square = Square(5)
print(f"Area of square: {square.area()}")
print(f"Perimeter of square: {square.perimeter()}")

Concepts Behind the Snippet

The key concepts are:

  • Abstraction: Hiding complex implementation details and exposing only the essential information to the user. ABCs enforce abstraction by defining a common interface.
  • Inheritance: Creating new classes from existing classes, inheriting their properties and methods. Subclasses inherit abstract methods from the ABC.
  • Polymorphism: The ability of objects of different classes to respond to the same method call in their own specific ways. ABCs facilitate polymorphism by defining a consistent interface that different classes can implement.
  • Contracts: ABCs define a contract that subclasses must adhere to. This ensures consistency and predictability in the behavior of related classes.

Real-Life Use Case

Consider a framework for processing different types of documents (e.g., PDF, Word, CSV). An abstract base class DocumentProcessor could define abstract methods like load_document, extract_text, and save_document. Concrete classes like PDFProcessor, WordProcessor, and CSVProcessor would then inherit from DocumentProcessor and implement these methods according to the specific document format.

This ensures that all document processors adhere to a consistent interface, making it easier to switch between different processors or add new ones without breaking the code.

Best Practices

Here are some best practices for using ABCs:

  • Use ABCs to define interfaces, not implementations. The ABC should primarily define abstract methods and properties, leaving the implementation details to the subclasses.
  • Consider using @abstractproperty for abstract properties that subclasses must define.
  • When designing a class hierarchy, identify the core functionalities that are common to all subclasses and define them as abstract methods in the ABC.
  • Avoid excessive use of ABCs. Use them when you need to enforce a specific interface or ensure that subclasses implement certain methods.
  • Document your ABCs clearly, explaining the purpose of each abstract method and property.

Interview Tip

When discussing ABCs in an interview, emphasize their role in enforcing contracts and promoting code reuse. Be prepared to explain how ABCs relate to the principles of abstraction, inheritance, and polymorphism. Provide concrete examples of how ABCs can be used to solve real-world problems.

A good answer should demonstrate an understanding of when to use ABCs, and why they are preferred over alternatives like informal interfaces (relying solely on documentation).

When to Use Them

Use ABCs when:

  • You need to enforce that subclasses implement certain methods.
  • You want to define a common interface for a group of related classes.
  • You want to ensure that all subclasses adhere to a specific contract.
  • You're building a framework or library that will be used by other developers.

Memory Footprint

ABCs themselves do not significantly increase memory footprint. The primary memory impact comes from the objects created from the concrete subclasses that inherit from the ABC. The size of these objects depends on the data they hold and the methods they implement.

Alternatives

Alternatives to ABCs include:

  • Informal Interfaces (Duck Typing): Relying on documentation and convention to ensure that classes implement the necessary methods. This approach is less strict and can lead to runtime errors if a class doesn't adhere to the interface.
  • Mixins: Classes that provide a set of methods that can be added to other classes through multiple inheritance. While mixins can provide some of the same benefits as ABCs, they don't enforce a contract in the same way.
  • Protocols (typing module): Introduced in Python 3.8, protocols allow for structural subtyping, where a class is considered a subtype of a protocol if it implements the required attributes and methods, regardless of inheritance.

Pros

  • Enforces Contracts: Guarantees that subclasses implement required methods.
  • Improves Code Organization: Defines a clear interface for related classes.
  • Enhances Maintainability: Makes it easier to understand and modify code by providing a consistent structure.
  • Facilitates Polymorphism: Allows objects of different classes to be treated uniformly.

Cons

  • Increased Complexity: Can add complexity to the codebase, especially if overused.
  • Less Flexible Than Duck Typing: Can be more restrictive than informal interfaces.
  • Potential for Over-Engineering: It's possible to use ABCs when a simpler solution would suffice.

FAQ

  • Can I instantiate an abstract base class directly?

    No, you cannot instantiate an abstract base class directly. Attempting to do so will raise a TypeError.
  • What happens if a subclass doesn't implement all abstract methods?

    If a subclass doesn't implement all abstract methods, it becomes an abstract class itself, and you cannot instantiate it. Attempting to instantiate it will also raise a TypeError.
  • How do I define an abstract property?

    You can define an abstract property using the @abstractproperty decorator in conjunction with the property function or the @property decorator. For example: python from abc import ABC, abstractproperty class MyAbstractClass(ABC): @abstractproperty def my_property(self): pass