Abstract Classes and Interfaces

Introduction

Abstraction is a key concept in Object-Oriented Programming (OOP) that focuses on hiding the implementation details while exposing only the necessary functionalities. In Python, abstraction is achieved using abstract classes and interfaces.

This tutorial will cover:

  1. What abstraction is and why it is needed
  2. Abstract classes and methods in Python
  3. The abc module and @abstractmethod decorator
  4. Difference between abstract classes and interfaces
  5. Real-world examples of abstraction

1. What is Abstraction?

Abstraction allows you to define a blueprint for a class without specifying the exact implementation. This ensures that different classes following the blueprint must implement the required methods.

For example, in a payment system, different payment methods like credit cards, UPI, and wallets should have a common structure but different implementations.

Key Benefits of Abstraction

Hides unnecessary details from the user 
Enforces a contract for subclasses to implement necessary methods 
Makes code more maintainable and scalable


2. Abstract Classes in Python

An abstract class is a class that cannot be instantiated and contains at least one abstract method. Abstract methods are methods that are declared but not implemented in the base class.

Creating an Abstract Class

Python provides the abc (Abstract Base Class) module to define abstract classes.

from abc import ABC, abstractmethod
class Vehicle(ABC):  # Abstract class
    @abstractmethod
    def start(self):
        pass  # No implementation
    @abstractmethod
    def stop(self):
        pass

Here, Vehicle is an abstract class with two abstract methods: start() and stop(). Any subclass of Vehicle must implement these methods.


3. Implementing an Abstract Class

A class that inherits from an abstract class must implement all abstract methods; otherwise, it will remain abstract itself.

Example: Implementing an Abstract Class

class Car(Vehicle):  # Inheriting from Vehicle
    def start(self):
        print("Car engine started.")
    def stop(self):
        print("Car engine stopped.")
class Bike(Vehicle):
    def start(self):
        print("Bike engine started.")
    def stop(self):
        print("Bike engine stopped.")
# car = Vehicle()  #  Error: Abstract classes cannot be instantiated
car = Car()
car.start()  # Output: Car engine started
car.stop()   # Output: Car engine stopped
bike = Bike()
bike.start()  # Output: Bike engine started
bike.stop()   # Output: Bike engine stopped

Abstract classes ensure that every subclass provides its own version of start() and stop().


4. Abstract Class with Concrete Methods

An abstract class can also have regular (concrete) methods that provide some default implementation.

class Bank(ABC):  
    def show_info(self):
        print("This is a bank.")
    @abstractmethod
    def get_interest_rate(self):
        pass
class SBI(Bank):
    def get_interest_rate(self):
        return 5.5
sbi = SBI()
sbi.show_info()  # Output: This is a bank.
print(sbi.get_interest_rate())  # Output: 5.5

Here, show_info() is a regular method and get_interest_rate() is an abstract method.


5. Interfaces in Python

Python does not have a separate interface keyword like Java. However, an interface can be implemented using an abstract class with only abstract methods.

Example: Defining an Interface

class Payment(ABC):  # This acts as an interface
    @abstractmethod
    def pay(self, amount):
        pass
class CreditCardPayment(Payment):
    def pay(self, amount):
        print(f"Paid {amount} using Credit Card.")
class UPIPayment(Payment):
    def pay(self, amount):
        print(f"Paid {amount} using UPI.")
payment1 = CreditCardPayment()
payment1.pay(1000)  # Output: Paid 1000 using Credit Card.
payment2 = UPIPayment()
payment2.pay(500)  # Output: Paid 500 using UPI.

Here, Payment acts as an interface, enforcing a pay() method in all subclasses.


6. Difference Between Abstract Classes and Interfaces

FeatureAbstract ClassInterface
Can contain concrete methods?YesNo
Can have attributes?YesNo
Supports multiple inheritance?No (Single inheritance)Yes (Multiple inheritance)
PurposeUsed for code reuse and abstractionUsed for defining a strict contract

 7. Real-World Example: Online Food Ordering System

Consider an online food delivery system where different types of orders exist.

class Order(ABC):  
    @abstractmethod
    def calculate_total(self):
        pass

class DineInOrder(Order):
    def calculate_total(self):
        print("Total calculated for dine-in order.")

class OnlineOrder(Order):
    def calculate_total(self):
        print("Total calculated for online order.")

order1 = DineInOrder()
order1.calculate_total()  # Output: Total calculated for dine-in order.

order2 = OnlineOrder()
order2.calculate_total()  # Output: Total calculated for online order.

The Order class defines an abstract method calculate_total(), which must be implemented by DineInOrder and OnlineOrder.


Summary

Abstraction hides implementation details and enforces necessary methods in subclasses.
Abstract classes cannot be instantiated and contain at least one abstract method.
The abc module and @abstractmethod decorator are used to create abstract classes.
Interfaces in Python are implemented using abstract classes with only abstract methods.
Abstract classes allow code reuse, while interfaces enforce a strict contract.