Skip to content

Four Pillars of OOP

OOP is built on four core principles: Encapsulation, Inheritance, Polymorphism, and Abstraction.

Definition: Encapsulation is the practice of bundling data (attributes) and the methods that operate on that data into a single unit (a class). It controls access to the data, protecting it from accidental or unauthorized modification.

Analogy: Think of a car’s engine. The driver interacts with the car through controls like the steering wheel and pedals (public methods), but doesn’t need to see or manipulate the internal engine components directly. Encapsulation hides the complex inner workings and provides a simple, controlled interface.

Implementation: Python uses name mangling to implement “private” attributes, which start with two underscores (__).

class Account:
def __init__(self, balance):
self.__balance = balance # Private attribute
def get_balance(self):
return self.__balance

Definition: Inheritance is a mechanism that allows a new class (derived class or child) to inherit attributes and methods from an existing class (base class or parent). This promotes code reuse and a logical “is-a” relationship (e.g., an ElectricCar is a Car).

Analogy: A child inherits traits like eye color or height from their parents. Similarly, a subclass inherits all the properties and behaviors of its superclass.

Types of Inheritance:

  • Single: One child class inherits from one parent class.
  • Multilevel: A class inherits from a parent, which in turn inherits from another class (e.g., Child inherits from Parent, and Parent inherits from Grandparent).
  • Hierarchical: Multiple classes inherit from a single parent class.
  • Multiple: A class inherits from more than one parent class.

Example:

class Car:
def start(self):
print("Car is starting.")
class ElectricCar(Car):
def charge(self):
print("Car is charging.")
tesla = ElectricCar()
tesla.start() # Inherited from the Car class
tesla.charge() # Defined in the ElectricCar class

Definition: Polymorphism means “many forms.” It allows objects of different classes to be treated as objects of a common superclass. This means a single function or method can behave differently based on the object it is called on.

Example: Method Overriding occurs when a derived class provides its own implementation of a method that is already defined in its parent class.

class Bird:
def sound(self):
print("Chirp")
class Sparrow(Bird):
def sound(self): # Overrides the parent method
print("Tweet")
bird = Sparrow()
bird.sound() # Output: Tweet (The overridden method is called)

Definition: Abstraction is the process of hiding complex implementation details and showing only the essential features of an object. It allows you to focus on what an object does rather than how it does it.

Abstract Classes:

  • An abstract class is a blueprint that cannot be instantiated on its own. It’s meant to be inherited by other classes.
  • Abstract classes often define abstract methods using the @abstractmethod decorator, which are methods without an implementation. Any concrete (non-abstract) subclass must provide an implementation for these methods.

Example:

from abc import ABC, abstractmethod
# Abstract Class
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self): # Must implement the abstract method
return 3.14 * self.radius ** 2
circle = Circle(5)
print(f"Circle Area: {circle.area()}") # Output: Circle Area: 78.5

Here, the Shape class abstracts the concept of a shape, requiring any subclass to implement the area method. This ensures a consistent interface for all shapes.