Python

Abstraction

YouTube

Object abstraction is a programming concept that refers to the idea of hiding the inner workings of an object from the outside world. It’s an important part of object-oriented programming (OOP) and helps to reduce the complexity of code by only exposing the necessary details to the user.

Abstraction and Object-Oriented Programming (OOP):

Abstraction is closely related to object-oriented programming. In OOP, you design classes to model real-world entities. Abstraction involves defining classes with relevant attributes (data) and methods (behaviour), while hiding the internal complexities.

Levels of Abstraction:

There are two main levels of abstraction in programming:

  • Class Level Abstraction: This involves creating classes that encapsulate data and behaviour relevant to a specific entity. Attributes represent data, and methods define behaviour. Other parts of the program interact with these classes without needing to know their internal details.
  • Interface Level Abstraction: This focuses on exposing only necessary methods and hiding implementation details. It helps in creating clean and well-defined interfaces between different components of a program.
Encapsulation:

Encapsulation is closely related to abstraction. It involves bundling data (attributes) and methods that operate on that data within a single unit, which is the class. Encapsulation helps in enforcing abstraction by restricting direct access to internal data and allowing controlled access via methods.

Abstract Classes:

In Python, abstract classes are used to create a blueprint for other classes. They define methods that subclasses must implement. Abstract classes cannot be instantiated on their own. The abc module provides the ABC metaclass for creating abstract base classes. By inheriting the ABC class and using an Abstract Method decorator, we can ensure that the Animal class can’t be instantiated, which could potentially cause malicious activity if someone were to access this in a running script.

from abc import ABC, abstractmethod

class Animal(ABC):
    def __init__(self, name):
        self.name = name
        
    @abstractmethod
    def speak(self):
        pass

animal = Animal("Doggo")
print(animal)
animal.speak()

# Output:
# TypeError: Can't instantiate abstract class Animal with abstract method speak
Interfaces:

Python doesn’t have a distinct “interface” keyword like some other programming languages. Instead, interfaces are implemented through abstract classes or using the concept of “duck typing,” where the behaviour of an object is determined by its methods and attributes rather than its explicit type.

Using Abstraction in Python:
  • Defining Abstract Base Classes: You can create abstract base classes using the ABC metaclass from the abc module. Subclasses must implement the methods defined in the abstract base class.
  • Polymorphism: Abstraction enables polymorphism, where different classes can implement the same methods with different behaviours. This makes it easier to switch between different implementations without affecting the rest of the code.
Benefits of Abstraction:
  • Modularity: Abstraction encourages modular design, enabling components to be developed and tested independently.
  • Reduced Complexity: By hiding internal details, abstraction simplifies code, making it easier to understand and maintain.
  • Code Reusability: Abstract classes and interfaces promote code reusability by providing a standardised structure for different implementations.
  • Adaptability: Abstraction allows you to change the internal implementation without affecting other parts of the program that depend on the abstraction.
Examples of Abstraction in Python:
  • Defining classes for different types of technology (computer, laptop, phone), with methods like start(), turn_off(), and type().
  • Creating different data storage classes (file storage, database storage, cloud storage) with methods like store_data() and retrieve_data().

Following on with our Vehicle example, you can see below that we are able to implement an abstract method called ‘slow_down’ which is then overwritten by the subclasses to tailor it to their specific needs. For example, the slow_down method requires a weight, however for the lorry class, we are able to adjust the speed in which it slows down depending on the weight of the vehicle.

from abc import abstractmethod

class Vehicle:
    def __init__(self, model, make, year, weight):
        self.model = model
        self.make = make
        self.year = year
        self.speed = 0
        self.weight = weight
        
    def move(self):
        if self.year > 1970:
            self.speed += 30
            print("You are going 30mph!")
            
    @abstractmethod
    def slow_down(self):
        pass

class Car(Vehicle):
    def __init__(self, model, make, year, weight):
        super().__init__(model, make, year, weight)
    
    def slow_down(self, weight): 
        if self.speed >= 1:
            self.speed -= 5

class Lorry(Vehicle):
    def __init__(self, model, make, year, weight):
        super().__init__(model, make, year, weight)
        
    def slow_down(self): 
        if self.speed >= 1:
            if self.weight > 100:
                self.speed -= 1
            elif self.weight > 75:
                self.speed -= 2
            elif self.weight > 50:
                self.speed -= 3
            else: 
                self.speed -= 4
    
car = Car("1 Series", "BMW", 2011, 24)
lorry = Lorry("Big Lorry", "Volkswagen", 2020, 74)
lorry2 = Lorry("Small Lorry", "Volkswagen", 2020, 54)
lorry2.move()
lorry2.slow_down()
print(lorry2.speed)