Abstraction

Updated Nov 29, 2025

Abstraction

Abstraction means hiding complex implementation details and showing only the essential features. It's like using a car - you don't need to know how the engine works, you just need to know how to use the steering wheel, pedals, and buttons.

To understand abstraction properly, we must first learn about Abstract Classes and Abstract Methods. These are the tools Python uses to achieve abstraction.


Abstract Methods (Quick Introduction)

Abstract Methods are methods declared in a parent class but not implemented. Child classes must provide their own implementation.

Key Points:

  • Use @abstractmethod decorator
  • Method has no body (just pass)
  • Child classes must implement it

Simple Example:

from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def calculate_area(self): pass # Child classes must implement this class Circle(Shape): def __init__(self, radius): self.radius = radius def calculate_area(self): # Must implement! return 3.14 * self.radius ** 2 # Can't create Shape directly # shape = Shape() # Error! circle = Circle(5) print(circle.calculate_area()) # Output: 78.5

Abstract Classes (Quick Introduction)

Abstract Classes are classes that cannot be instantiated directly. They serve as templates with both abstract methods (must be implemented) and regular methods (can be used as-is).

Key Points:

  • Use ABC (Abstract Base Class) from abc module
  • Can have both abstract and regular methods
  • Can't create object directly
  • Forces child classes to implement required methods

Simple Example:

from abc import ABC, abstractmethod class Vehicle(ABC): def __init__(self, brand): self.brand = brand @abstractmethod def start(self): pass # Must be implemented def get_info(self): # Regular method - can be used as-is return f"{self.brand} vehicle" class Car(Vehicle): def start(self): # Must implement! print(f"{self.get_info()} is starting!") # Can't create Vehicle directly # vehicle = Vehicle("Toyota") # Error! car = Car("Toyota") car.start() # Output: Toyota vehicle is starting!

Now that we understand abstract classes and methods, let's see how they help us achieve abstraction in real examples:

To demonstrate abstraction, consider the following example where we want to send messages through different services:

❌ Without Abstraction

# messaging.py class EmailService: def __init__(self): # Complex email setup self.smtp_server = "smtp.example.com" self.port = 587 self.ssl_enabled = True self.connection_timeout = 30 def connect_to_server(self): print("Connecting to SMTP server...") print(f"Server: {self.smtp_server}, Port: {self.port}") print("Establishing SSL connection...") print("Connection established!") def authenticate(self, username, password): print(f"Authenticating user: {username}") print("Verifying credentials...") print("Authentication successful!") def send_message(self, to, subject, body): self.connect_to_server() self.authenticate("user@example.com", "password") print(f"Sending email to {to}...") print(f"Subject: {subject}") print(f"Body: {body}") print("Email sent successfully!") # User has to know all the complex details email = EmailService() email.connect_to_server() email.authenticate("user@example.com", "password") email.send_message("friend@example.com", "Hello", "How are you?")

Problem: Users have to deal with all the complex details like SMTP servers, ports, authentication, etc. This makes it hard to use and understand.

✅ With Abstraction

# message_service.py from abc import ABC, abstractmethod class MessageService(ABC): @abstractmethod def send(self, recipient, message): pass # Child classes will implement this
# email_service.py from message_service import MessageService class EmailService(MessageService): def __init__(self): # Complex setup hidden from user self.smtp_server = "smtp.example.com" self.port = 587 self.ssl_enabled = True self.connection_timeout = 30 def _connect_to_server(self): # Private method (starts with _) print("Connecting to SMTP server...") print(f"Server: {self.smtp_server}, Port: {self.port}") print("Establishing SSL connection...") print("Connection established!") def _authenticate(self): print("Authenticating...") print("Authentication successful!") def send(self, recipient, message): # Simple interface - hides all complexity self._connect_to_server() self._authenticate() print(f"📧 Email sent to {recipient}: {message}")
# sms_service.py from message_service import MessageService class SMSService(MessageService): def __init__(self): # Complex SMS gateway setup hidden self.api_key = "secret_key" self.gateway_url = "https://sms-gateway.com" def _connect_to_gateway(self): print("Connecting to SMS gateway...") print("Connection established!") def send(self, recipient, message): # Simple interface - same as EmailService self._connect_to_gateway() print(f"📱 SMS sent to {recipient}: {message}")
# main.py from email_service import EmailService from sms_service import SMSService # User only needs to know the simple interface def send_notification(service, recipient, message): service.send(recipient, message) # Simple - no complex details! # Use email service email = EmailService() send_notification(email, "alice@example.com", "Hello from email!") # Use SMS service - same simple interface sms = SMSService() send_notification(sms, "+1234567890", "Hello from SMS!") # Both services work the same way - abstraction at work!

Now:

  • Users only see the simple interface (send() method).
  • All complex details are hidden inside the classes.
  • Different services can be used interchangeably.

This approach makes the code:

  • ✅ Easier to use - simple interface
  • ✅ Less confusing - no need to know implementation details
  • ✅ More flexible - can swap implementations easily

🎁 Bonus: Abstract Classes vs Interfaces (Java Comparison)

What is an Interface?

In languages like Java, an Interface is a contract that defines what methods a class must have, but provides no implementation at all. It's like a checklist - "you must have these methods."

Abstract Class vs Interface

FeatureAbstract Class (Python)Interface (Java)
Can have methods with implementation?✅ Yes (regular methods)❌ No (only method signatures)
Can have abstract methods?✅ Yes✅ Yes (all methods are abstract)
Can have variables/attributes?✅ Yes❌ No (only constants)
Can have constructors?✅ Yes❌ No
Multiple inheritance?✅ Yes (Python supports it)✅ Yes (can implement multiple interfaces)
PurposeTemplate with some implementationPure contract/checklist

Python's Approach

Python doesn't have separate "interfaces" like Java. Instead, Python uses:

  1. Abstract Classes - Can have both abstract and regular methods (like Java's abstract classes)
  2. Duck Typing - "If it walks like a duck, it's a duck" - Python doesn't check types strictly

Example: Java Interface (for comparison)

// Java Interface Example (for understanding) interface MessageService { void send(String recipient, String message); // No implementation void connect(); // No implementation } class EmailService implements MessageService { public void send(String recipient, String message) { // Must implement } public void connect() { // Must implement } }

Example: Python Abstract Class (what we use)

# Python Abstract Class (what we actually use) from abc import ABC, abstractmethod class MessageService(ABC): @abstractmethod def send(self, recipient, message): pass # Must be implemented @abstractmethod def connect(self): pass # Must be implemented def get_status(self): # Can have implementation! return "Service is ready" # This is allowed in abstract class class EmailService(MessageService): def send(self, recipient, message): # Must implement print(f"Email sent to {recipient}") def connect(self): # Must implement print("Connected to email server") # Can use get_status() as-is or override it

Key Differences

Java Interface:

  • Only method signatures (no body)
  • No variables (only constants)
  • Pure contract

Python Abstract Class:

  • Can have abstract methods (must be implemented)
  • Can have regular methods (can be used as-is)
  • Can have variables and constructors
  • More flexible

When to Use What?

Use Abstract Class when:

  • You want to provide some common implementation
  • Child classes share some common code
  • You want to force certain methods but provide others

Use Interface (in Java) when:

  • You only want a contract (no implementation)
  • Multiple unrelated classes need the same contract
  • You want pure abstraction

In Python:

  • Use Abstract Classes for both cases
  • Python's flexibility allows abstract classes to work like interfaces when needed

Quick Summary

  • Abstraction: Hiding complex details, showing only essential features
  • Abstract Methods: Methods that must be implemented by child classes
  • Abstract Classes: Classes that can't be instantiated, serve as templates
  • Python vs Java: Python uses abstract classes for both abstract classes and interfaces
  • Key Benefit: Makes code easier to use and more flexible

Abstraction helps you:

  • ✅ Hide complexity from users
  • ✅ Create simple, easy-to-use interfaces
  • ✅ Make code more maintainable
  • ✅ Allow different implementations to work the same way

🎉 End

Abstraction is one of the four pillars of OOP. It helps you build systems that are easy to use and understand, even when the underlying implementation is complex!