DP 2: Interfaces [Part 1] - ABC Abstract Base Classes

Programming to Interfaces rather than Implementation specifics
design patterns
Author

Tony Phung

Published

December 6, 2024

1. Introduction

1.1 The Scenario

Focusing on specifics or details of Implementation

1.2 The Problem

Leads to tightly coupled or difficult to modify code.

1.3 (One of) The Solution(s):

The Program to Interfaces, not Implementations principle

2. What does the principle mean?

An interface defines a contract for classes:

  • specifying a set of methods
  • that must be implemented.

3. Laymens

This principle encourages to:

  • code against an interface
  • rather than a concrete class.

4. Techniques

In Python, interfaces can be implemented using two primary techniques:

  • abstract base classes (ABCs)
  • and protocols.

5. Psuedo-Code

  • import from abc, ABC, abstractmethod
  • create Interface class inheriting from ABC (“Abstract Base Class”)
  • add class method some_method decorated by abstractmethod: making the method
    • add parameter param: str required for any sub-class inherited the Interface
  • create MyClass inheriting Interface
  • add (required) class method some_method
    • add parameter param: str
    • #TEST: [Can we completely change the method? I assume yes.]
  • test by creating instance of MyClass and running some_method()

6. Code

6.1 Scenario 1, Part 1: ABC and @abstractmethod

By decorating do_I_exist() with @abstractmethod of ABC class TonysExistentialCrisisBase:

  • This applies the implementation requirement that a do_I_exist method must be implemented in all sub-classes.
from abc import ABC, abstractmethod

class TonysExistentialCrisisBase(ABC):
    def __init__(self, name: str):
        self.name=name
        
    @abstractmethod
    def do_I_exist(self, am_i_alive: bool):
        pass

6.2 Scenario 1, Part 2: No Required Method in Sub-Class

class MyHumanBeingClass(TonysExistentialCrisisBase):
    pass
  • Therefore, Python raises a very clear error, when an instance MyHumanBeingClass is attempted to be created
  • Since our sub-class does not have it’s own implementation of do_I_exist method
dave = MyHumanBeingClass("Dave")
dave
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[3], line 1
----> 1 dave = MyHumanBeingClass("Dave")
      2 dave

TypeError: Can't instantiate abstract class MyHumanBeingClass with abstract method do_I_exist

6.3 Scenario 2, Part 1: Sub-Class With Required Abstract Method

class MyHumanBeingClass(TonysExistentialCrisisBase):
    def do_I_exist(self, am_i_alive: bool=True):
        print("Cogito, ergo sum...👽")

6.4 Scenario 2, Part 2: No errors

By adding the required method, an instance of MyHumanBeingClass is allowed.

james = MyHumanBeingClass("James")
james.do_I_exist()
Cogito, ergo sum...👽