Welcome to Day 3! Today we explore how classes share, extend, and adapt behavior without duplicating code.
- Inheritance: Creating new classes based on existing ones to reuse code and establish hierarchies.
-
Method Overriding &
super(): Redefining parent class behaviors in child classes while retaining access to parent implementations. - Polymorphism & Duck Typing: Operating on different object types through a shared interface or common set of methods.
1. Inheritance Structures 🌳
Python supports three primary flavors of inheritance:
SINGLE INHERITANCE MULTILEVEL INHERITANCE MULTIPLE INHERITANCE
┌──────────┐ ┌──────────┐ ┌───────┐ ┌─────────┐
│ Parent │ │ Grandpa │ │ Mixin │ │ BaseClass│
└────┬─────┘ └────┬─────┘ └───┬───┘ └───┬─────┘
│ │ │ │
▼ ▼ └─────┬─────┘
┌──────────┐ ┌──────────┐ ▼
│ Child │ │ Parent │ ┌───────────┐
└──────────┘ └────┬─────┘ │ Child │
│ └───────────┘
▼
┌──────────┐
│ Child │
└──────────┘
Enter fullscreen mode Exit fullscreen mode
- Single Inheritance: One child class inherits from one direct parent class.
- Multilevel Inheritance: A child class inherits from a parent class, which itself inherits from a grandparent class (a chain).
- Multiple Inheritance: A single child class inherits directly from two or more parent classes.
2. Method Overriding & super() 🔄
- Method Overriding: Occurs when a child class defines a method with the exact same name as a method in its parent class. The child's method replaces or modifies the parent behavior.
-
super(): A built-in function that lets you invoke methods from a parent class inside the child class. This prevents code repetition when extending parent functionality.
🌱 Quick Example
class Animal:
def __init__(self, name: str):
self.name = name
def make_sound(self) -> str:
return "Generic animal sound"
class Dog(Animal):
def __init__(self, name: str, breed: str):
# Call parent constructor using super()
super().__init__(name)
self.breed = breed
# Override parent method
def make_sound(self) -> str:
parent_sound = super().make_sound()
return f"{parent_sound} -> Woof! 🐾"
dog = Dog("Rex", "German Shepherd")
print(dog.make_sound()) # Output: Generic animal sound -> Woof! 🐾
Enter fullscreen mode Exit fullscreen mode
3. Polymorphism & Duck Typing 🦆
Polymorphism ("many shapes") allows different classes to respond to the same method call in their own unique way.
In Python, polymorphism is heavily tied to Duck Typing:
"If it walks like a duck and quacks like a duck, it's a duck."
Python doesn't care about explicit class hierarchies or explicit interface contracts—if an object implements the expected method (e.g., .calculate_pay()), Python will happily execute it.
┌───────────────────────────────┐
│ Payroll Processor Service │
└───────────────┬───────────────┘
│
Calls .calculate_pay() on each
│
┌──────────────────────────────┼──────────────────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ FullTime │ │ Executive│ │Contractor│
│ Employee │ │ Manager │ │ (No Base)│
└──────────┘ └──────────┘ └──────────┘
Enter fullscreen mode Exit fullscreen mode
4. Practice Challenge: Building an Employee Management System 🏢
Here is a enterprise-ready Employee Management System demonstrating Single, Multilevel, and Multiple Inheritance, Method Overriding with super(), and Duck Typing via a unified PayrollProcessor.
Step 1: Initialize Your Workspace
uv init oop_day3 && cd oop_day3
touch employee_system.py
Enter fullscreen mode Exit fullscreen mode
Step 2: Implement employee_system.py
# employee_system.py
from typing import List, Any
# ==========================================
# 1. BASE CLASS (PARENT)
# ==========================================
class Employee:
"""Base class for all salaried employees."""
def __init__(self, emp_id: str, name: str, base_salary: float):
self.emp_id = emp_id
self.name = name
self.base_salary = base_salary
def calculate_pay(self) -> float:
"""Calculates standard monthly pay."""
return round(self.base_salary, 2)
def get_details(self) -> str:
return f"[{self.emp_id}] {self.name} | Role: Employee | Base Salary: ${self.base_salary:,.2f}"
# ==========================================
# 2. SINGLE INHERITANCE: DEVELOPER
# ==========================================
class Developer(Employee):
"""Inherits directly from Employee (Single Inheritance)."""
def __init__(self, emp_id: str, name: str, base_salary: float, tech_stack: str):
super().__init__(emp_id, name, base_salary)
self.tech_stack = tech_stack
# Override calculate_pay to add a tech allowance
def calculate_pay(self) -> float:
tech_bonus = 300.00 # Fixed monthly tooling stipend
return round(super().calculate_pay() + tech_bonus, 2)
def get_details(self) -> str:
return f"[{self.emp_id}] {self.name} | Role: Developer ({self.tech_stack})"
# ==========================================
# 3. MULTILEVEL INHERITANCE: MANAGER -> EXECUTIVE
# ==========================================
class Manager(Employee):
"""Inherits from Employee (Level 1)."""
def __init__(self, emp_id: str, name: str, base_salary: float, team_size: int):
super().__init__(emp_id, name, base_salary)
self.team_size = team_size
def calculate_pay(self) -> float:
team_allowance = self.team_size * 150.00
return round(super().calculate_pay() + team_allowance, 2)
def get_details(self) -> str:
return f"[{self.emp_id}] {self.name} | Role: Manager | Team Size: {self.team_size}"
class Executive(Manager):
"""Inherits from Manager (Level 2 - Multilevel Inheritance: Employee -> Manager -> Executive)."""
def __init__(self, emp_id: str, name: str, base_salary: float, team_size: int, stock_options: int):
super().__init__(emp_id, name, base_salary, team_size)
self.stock_options = stock_options
def calculate_pay(self) -> float:
executive_bonus = 2500.00
# Combines base salary + team allowance (from Manager) + executive bonus
return round(super().calculate_pay() + executive_bonus, 2)
def get_details(self) -> str:
return f"[{self.emp_id}] {self.name} | Role: Executive | Options: {self.stock_options} units"
# ==========================================
# 4. MULTIPLE INHERITANCE / MIXIN: AUDITABLE
# ==========================================
class ComplianceAuditableMixin:
"""A standalone mixin class that adds auditing capabilities."""
def log_audit(self, action: str) -> None:
print(f"[AUDIT LOG] Entity Action Recorded: '{action}'")
class TechLead(Developer, ComplianceAuditableMixin):
"""Inherits from Developer AND ComplianceAuditableMixin (Multiple Inheritance)."""
def __init__(self, emp_id: str, name: str, base_salary: float, tech_stack: str, projects_count: int):
Developer.__init__(self, emp_id, name, base_salary, tech_stack)
self.projects_count = projects_count
def get_details(self) -> str:
return f"[{self.emp_id}] {self.name} | Role: Tech Lead | Projects: {self.projects_count}"
# ==========================================
# 5. DUCK TYPING: CONTRACTOR (NO BASE CLASS)
# ==========================================
class ExternalContractor:
"""Does NOT inherit from Employee, but implements calculate_pay() and get_details()."""
def __init__(self, contractor_id: str, name: str, hourly_rate: float, hours_worked: float):
self.contractor_id = contractor_id
self.name = name
self.hourly_rate = hourly_rate
self.hours_worked = hours_worked
def calculate_pay(self) -> float:
return round(self.hourly_rate * self.hours_worked, 2)
def get_details(self) -> str:
return f"[{self.contractor_id}] {self.name} | External Contractor ({self.hours_worked} hrs @ ${self.hourly_rate}/hr)"
# ==========================================
# 6. UNIFIED PAYROLL PROCESSOR (POLYMORPHISM)
# ==========================================
class PayrollProcessor:
"""Uses Polymorphism & Duck Typing to process pay across any compatible worker object."""
@staticmethod
def process_payroll(workers: List[Any]) -> None:
print("==========================================================")
print(" MONTHLY PAYROLL REPORT ")
print("==========================================================")
total_payout = 0.0
for worker in workers:
# Duck typing in action: as long as worker has get_details() and calculate_pay(), it works
details = worker.get_details()
pay = worker.calculate_pay()
total_payout += pay
print(f"{details}\n └─ Calculated Payout: ${pay:,.2f}\n")
print("----------------------------------------------------------")
print(f" TOTAL SYSTEM PAYOUT: ${total_payout:,.2f}")
print("==========================================================\n")
# ==========================================
# TEST EXECUTION SUITE
# ==========================================
if __name__ == "__main__":
# Create instances across various inheritance patterns
dev = Developer("EMP-101", "Alice Chen", base_salary=7500.00, tech_stack="Python/FastAPI")
mgr = Manager("EMP-102", "Bob Smith", base_salary=9000.00, team_size=5)
exec_officer = Executive("EMP-103", "Carol Danvers", base_salary=15000.00, team_size=20, stock_options=5000)
# Multiple Inheritance instance
tech_lead = TechLead("EMP-104", "David Miller", base_salary=11000.00, tech_stack="Distributed Systems", projects_count=3)
tech_lead.log_audit("Approved Architecture Review") # Mixin functionality
# Duck Typing instance (No inheritance from Employee class)
contractor = ExternalContractor("CONT-801", "Eva Green", hourly_rate=85.00, hours_worked=120)
# Heterogeneous collection passed into PayrollProcessor
workforce = [dev, mgr, exec_officer, tech_lead, contractor]
# Run Polymorphic Payroll
PayrollProcessor.process_payroll(workforce)
Enter fullscreen mode Exit fullscreen mode
Step 3: Run & Verify Execution
uv run employee_system.py
Enter fullscreen mode Exit fullscreen mode
Output Summary
[AUDIT LOG] Entity Action Recorded: 'Approved Architecture Review'
==========================================================
MONTHLY PAYROLL REPORT
==========================================================
[EMP-101] Alice Chen | Role: Developer (Python/FastAPI)
└─ Calculated Payout: $7,800.00
[EMP-102] Bob Smith | Role: Manager | Team Size: 5
└─ Calculated Payout: $9,750.00
[EMP-103] Carol Danvers | Role: Executive | Options: 5000 units
└─ Calculated Payout: $20,500.00
[EMP-104] David Miller | Role: Tech Lead | Projects: 3
└─ Calculated Payout: $11,300.00
[CONT-801] Eva Green | External Contractor (120 hrs @ $85.0/hr)
└─ Calculated Payout: $10,200.00
----------------------------------------------------------
TOTAL SYSTEM PAYOUT: $59,550.00
==========================================================
Enter fullscreen mode Exit fullscreen mode
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.