Introduction
Object-oriented programming (OOP) is a programming paradigm that organizes software design around data, or objects, rather than functions and logic. An object is a bundle of state (attributes) and behavior (methods) modeled after real-world or conceptual entities. OOP became dominant because it maps naturally to how humans reason about systems: a Car has wheels and a speed, and it can accelerate or brake. Languages like Python, Java, C++, and C# all support OOP, though each implements its details slightly differently.
Cricket analogy: OOP models a cricketer the way a scout's notebook does: a player object bundles attributes like batting average and strike rate with behaviors like 'bat' or 'bowl,' letting analysts reason about Kohli or Bumrah the same natural way they'd describe them in conversation.
Explanation
OOP rests on four foundational pillars. Encapsulation bundles data and the methods that operate on it into a single unit (a class) and restricts direct access to some of an object's internal state, exposing only what is necessary through a controlled interface. Abstraction hides complex implementation details behind a simple, well-defined interface, letting users of a class interact with 'what' it does rather than 'how' it does it. Inheritance allows a new class to acquire the attributes and methods of an existing class, enabling code reuse and the modeling of 'is-a' relationships (a Dog is an Animal). Polymorphism allows objects of different classes to be treated through a common interface, with each class providing its own specific behavior for shared method names. Together these four pillars let developers build systems that are modular, reusable, and easier to reason about as they grow.
Cricket analogy: A franchise practices encapsulation by keeping a bowler's exact training regimen private inside the team's coaching staff while only revealing match-day fitness status publicly; abstraction lets fans watch Bumrah bowl a yorker without knowing his exact wrist mechanics; inheritance lets a 'PaceBowler' class extend a base 'Player' class reusing its fielding logic; polymorphism lets both a spinner and a pacer respond to the same 'bowl()' call with completely different deliveries.
Example
from abc import ABC, abstractmethod
class Shape(ABC):
"""Abstraction: defines a common interface for all shapes."""
def __init__(self, name):
self._name = name # Encapsulation: internal state
@abstractmethod
def area(self):
"""Every concrete shape must implement this."""
raise NotImplementedError
class Circle(Shape): # Inheritance: Circle is-a Shape
def __init__(self, radius):
super().__init__("Circle")
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
class Rectangle(Shape): # Inheritance: Rectangle is-a Shape
def __init__(self, width, height):
super().__init__("Rectangle")
self.width = width
self.height = height
def area(self):
return self.width * self.height
# Polymorphism: same method call, different behavior per class
shapes = [Circle(3), Rectangle(4, 5)]
for shape in shapes:
print(f"{shape._name} area: {shape.area():.2f}")Analysis
In the example, Shape demonstrates abstraction by defining an area() contract without specifying how each shape computes it. _name demonstrates encapsulation, a convention signaling internal state that callers should not modify directly. Circle and Rectangle demonstrate inheritance by extending Shape and reusing its constructor logic via super().__init__(). The loop that calls shape.area() on each object demonstrates polymorphism: the same method call produces different, type-appropriate results without the caller needing to know which concrete class it is dealing with. Each pillar has a dedicated deep-dive topic elsewhere in this module; this lesson is meant only to show how they fit together.
Cricket analogy: A franchise's generic 'Player' contract defines that everyone must have a 'perform()' method (abstraction) without saying how; a bowler's average being kept internal and only exposed through official stats is encapsulation; a 'PaceBowler' extending 'Player' and reusing its fielding setup via a base constructor is inheritance; and calling 'perform()' on both a batter and a bowler in the same loop, each producing different results, is polymorphism.
Key Takeaways
- Encapsulation bundles data and behavior together and restricts direct access to internal state.
- Abstraction exposes a simple interface while hiding implementation complexity.
- Inheritance lets a class reuse and extend another class's attributes and methods.
- Polymorphism lets different classes respond to the same method call in their own way.
Practice what you learned
1. Which of the following is NOT one of the four pillars of OOP?
2. What does abstraction primarily achieve in OOP?
3. In the example code, what OOP pillar does the loop `for shape in shapes: shape.area()` demonstrate?
4. Which relationship does inheritance typically model?
Was this page helpful?
You May Also Like
Classes and Objects
How classes act as blueprints for objects, and the difference between class attributes and instance attributes.
Encapsulation
How Python conventions for protected and private attributes, plus properties, let classes control access to their internal state.
Inheritance
How single inheritance, `super().__init__()`, and method overriding let subclasses reuse and specialize parent class behavior.
Polymorphism and Abstraction
Distinguishing polymorphism (same interface, different implementations) from abstraction (hiding implementation details) using Python's abc module.
SOLID Principles Overview
A guided tour of the five SOLID design principles that make object-oriented code easier to maintain and extend.
Related Reading
Related Study Notes in Software Engineering
Browse all study notesMicroservices Study Notes
Software Architecture · 30 topics
Software EngineeringTesting & TDD Study Notes
Software Testing · 30 topics
Software EngineeringDesign Patterns Study Notes
Software Design · 30 topics
Software EngineeringGit & Version Control Study Notes
Bash · 40 topics
Software EngineeringSystem Design Study Notes
Architecture · 40 topics