Skip to content

Abstraction

Abstraction hides complex implementation details and shows only the necessary features, reducing complexity for users.


What is Abstraction

1. Hide Complexity

Show only essential features while hiding implementation details.

2. High-Level Interface

Users interact with objects at a high level without understanding internals.

3. Essential Features

Focus on what an object does, not how it does it.


Abstract Base Classes

1. Using ABC Module

from abc import ABC, abstractmethod

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

Defines a contract that subclasses must follow.

2. Cannot Instantiate

shape = Shape()  # TypeError!

Abstract classes cannot be instantiated directly.

3. Must Implement

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):  # Must implement
        return self.width * self.height

@abstractmethod

1. Required Methods

class MyBase(ABC):
    @abstractmethod
    def must_override(self):
        pass

Subclasses must implement this method.

2. Enforcement

class Incomplete(MyBase):
    pass

obj = Incomplete()  # TypeError!

Python prevents instantiation if abstract methods aren't implemented.

3. Complete Implementation

class Complete(MyBase):
    def must_override(self):
        return "Implemented!"

obj = Complete()  # Works

Abstract vs Optional

1. Required Methods

class Dataset(ABC):
    @abstractmethod
    def __getitem__(self, index):
        pass  # Must override

    @abstractmethod
    def __len__(self):
        pass  # Must override

2. Optional Methods

def __add__(self, other):
    return ConcatDataset([self, other])

No @abstractmethod = optional to override.

3. Mixed Approach

class MyDataset(Dataset):
    def __getitem__(self, index):  # Required
        return self.data[index]

    def __len__(self):  # Required
        return len(self.data)

    # __add__ inherited - optional

Abstract Decorators

1. Abstract Class Method

class MyBase(ABC):
    @classmethod
    @abstractmethod
    def create(cls):
        pass

2. Abstract Static Method

class MyBase(ABC):
    @staticmethod
    @abstractmethod
    def validate(data):
        pass

3. Abstract Property

class MyBase(ABC):
    @property
    @abstractmethod
    def name(self):
        pass

Real-World Example

1. Shape Hierarchy

from abc import ABC, abstractmethod

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

    @abstractmethod
    def perimeter(self):
        pass

2. Concrete Shapes

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def perimeter(self):
        return 2 * (self.width + self.height)

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14159 * self.radius ** 2

    def perimeter(self):
        return 2 * 3.14159 * self.radius

3. Polymorphic Use

shapes = [Rectangle(3, 4), Circle(5)]
for shape in shapes:
    print(f"Area: {shape.area()}")

Benefits

1. Contract Enforcement

Guarantees subclasses implement required methods.

2. Clear Interface

Defines what operations are available.

3. Design Consistency

All implementations follow the same structure.


Common Patterns

1. Template Method

class Algorithm(ABC):
    @abstractmethod
    def step_one(self):
        pass

    @abstractmethod
    def step_two(self):
        pass

    def execute(self):  # Template
        self.step_one()
        self.step_two()

2. Strategy Pattern

class Strategy(ABC):
    @abstractmethod
    def execute(self, data):
        pass

3. Factory Pattern

class Creator(ABC):
    @abstractmethod
    def create_product(self):
        pass

Key Takeaways

  • Abstraction hides implementation details.
  • ABC module enforces contracts.
  • @abstractmethod marks required methods.
  • Cannot instantiate abstract classes.
  • Enables polymorphic designs.

Runnable Example: abstract_base_classes_examples.py

"""Abstract Base Classes (ABC) - Defining contracts"""
from abc import ABC, abstractmethod

# =============================================================================
# Definitions
# =============================================================================

class PaymentProcessor(ABC):
    """Abstract interface for payment processing"""

    @abstractmethod
    def process_payment(self, amount):
        """All processors must implement this"""
        pass

    @abstractmethod
    def refund(self, transaction_id):
        """All processors must implement this"""
        pass

    def log_transaction(self, details):
        """Common implementation for all"""
        print(f"Logged: {details}")

class StripeProcessor(PaymentProcessor):
    def process_payment(self, amount):
        print(f"Processing ${amount} via Stripe")
        self.log_transaction(f"Stripe: ${amount}")

    def refund(self, transaction_id):
        print(f"Refunding Stripe transaction {transaction_id}")

class PayPalProcessor(PaymentProcessor):
    def process_payment(self, amount):
        print(f"Processing ${amount} via PayPal")
        self.log_transaction(f"PayPal: ${amount}")

    def refund(self, transaction_id):
        print(f"Refunding PayPal transaction {transaction_id}")

# Polymorphism with abstraction
def process_order(processor: PaymentProcessor, amount):
    processor.process_payment(amount)

# =============================================================================
# Main
# =============================================================================

if __name__ == "__main__":
    stripe = StripeProcessor()
    paypal = PayPalProcessor()

    process_order(stripe, 100)
    process_order(paypal, 50)