๐Ÿฆž Abstraction in Python: Daliโ€™s Lobster Telephone Edition#

๐Ÿš€ Introduction#

Abstraction is a fundamental concept in object-oriented programming that allows us to hide complex implementation details and expose only what is necessary. This makes code simpler, more modular, and easier to manage.

By the end of this guide, you will:

  • Understand the concept of abstraction and its benefits.

  • Learn how to create abstract classes and methods in Python.

  • Explore abstraction using a surreal analogyโ€”Daliโ€™s Lobster Telephone!

๐ŸŽจ What is Abstraction?#

Abstraction allows developers to define a blueprint for classes without specifying all implementation details. This is especially useful when working with multiple related objects that share common behavior but implement details differently.

Abstraction is like a placeholder that defines what an object can do without specifying how it does it. This allows us to create a common interface for different classes, making our code more modular and easier to maintain.

Why is Abstraction Useful?#

  • Encapsulation: Hides unnecessary details and provides a clear interface.

  • Code Organization: Defines structured class hierarchies.

  • Scalability: New classes can extend abstract ones without modifying existing code.

๐Ÿฆž Daliโ€™s Lobster Telephone and Abstraction#

Imagine Daliโ€™s Lobster Telephone, an artwork where a lobster replaces the phoneโ€™s receiver. While the phone functions normally, its real implementation details remain hidden to usersโ€”they only interact with the surreal concept of a telephone.

In programming, abstract classes work the same way: they provide a clear interface (like a telephoneโ€™s dial and receiver) but leave the exact implementation to subclasses.

Class Hierarchy Diagram#

classDiagram
AbstractTelephone <|-- ClassicTelephone
AbstractTelephone <|-- LobsterTelephone
class AbstractTelephone{
+call()
}
class ClassicTelephone{
+call()
}
class LobsterTelephone{
+call()
}

๐Ÿ“ž Creating an Abstract Telephone Class#

from abc import ABC, abstractmethod

class AbstractTelephone(ABC):
    def __init__(self, model):
        self.model = model

    @abstractmethod
    def call(self, number):
        """Abstract method that must be implemented in subclasses."""
        pass

Key Features:#

  • AbstractTelephone is an abstract class using ABC (Abstract Base Class).

  • call() is an abstract method, meaning subclasses must define their own implementation.

โ˜Ž๏ธ Implementing Different Telephone Types#

Just like how the Lobster Telephone is an artistic reimagination of a phone, subclasses will implement calling in their own way.

Classic Telephone (Normal Behavior)#

class ClassicTelephone(AbstractTelephone):
    def call(self, number):
        return f"๐Ÿ“ž Dialing {number} on a classic telephone."

Lobster Telephone (Surreal Behavior)#

class LobsterTelephone(AbstractTelephone):
    def call(self, number):
        return f"๐Ÿฆž Calling {number}... but the lobster just stares at you."

Key Features:#

  • Each subclass implements call() differently, respecting the abstract method contract.

  • ClassicTelephone follows expected behavior, while LobsterTelephone behaves in a surreal, unexpected way.

Broken Telephone (Incomplete Implementation)#

class BrokenTelephone(AbstractTelephone):
    def nothing(self, number):
        return f"๐Ÿฆž Calling {number}... but the lobster just stares at you."

๐ŸŽญ Using Abstraction in Action#

phones = [ClassicTelephone("Rotary Phone"), LobsterTelephone("Daliโ€™s Art Phone")]

for phone in phones:
    print(phone.call("555-1234"))
๐Ÿ“ž Dialing 555-1234 on a classic telephone.
๐Ÿฆž Calling 555-1234... but the lobster just stares at you.

If we try to instantiate BrokenTelephone, we get an error because it hasnโ€™t implemented the abstract method call(). This enforces that the subclasses must have a call method.

BrokenTelephone("Rotary Phone")

Output:#

๐Ÿ“ž Dialing 555-1234 on a classic telephone.
๐Ÿฆž Calling 555-1234... but the lobster just stares at you.

Why is This Useful?#

โœ… Ensures a common interface (call) for all phones.

โœ… Allows flexibility in behaviorโ€”some phones work normally, some are surreal!

โœ… New telephone types can be added without modifying existing code.

๐Ÿ›  More Examples of Abstraction#

Example 1: Using an Abstract Class for Payment Systems#

class PaymentProcessor(ABC):
    @abstractmethod
    def process_payment(self, amount):
        pass


class CreditCardPayment(PaymentProcessor):
    def process_payment(self, amount):
        return f"๐Ÿ’ณ Processing credit card payment of ${amount}."


class CryptoPayment(PaymentProcessor):
    def process_payment(self, amount):
        return f"๐Ÿช™ Processing cryptocurrency payment of ${amount}."
    
list_of_classes = [CreditCardPayment(), CryptoPayment()]

for i in list_of_classes:
    print(i.process_payment(100))
๐Ÿ’ณ Processing credit card payment of $100.
๐Ÿช™ Processing cryptocurrency payment of $100.

๐Ÿ“Œ Key Takeaways#

โœ… Abstraction allows defining common interfaces while hiding implementation details.

โœ… Abstract classes cannot be instantiated directlyโ€”they provide blueprints for subclasses.

โœ… Subclasses must implement abstract methods, ensuring consistency across different implementations.

โœ… Like Daliโ€™s Lobster Telephone, abstraction lets us interact with surreal or hidden functionality without understanding the full mechanics.

๐Ÿฆž Just as Dali reimagined the telephone, abstraction in Python allows us to redefine functionality while preserving a structured interface!