Module 5 ยท Lesson 16

Inheritance and Polymorphism

๐Ÿ Pythonโฑ 15 min read๐Ÿ“– Advanced OOP

Inheritance

Inheritance lets a class (child/subclass) inherit attributes and methods from another class (parent/superclass). Use it when there's a genuine "is-a" relationship between objects.

class Animal: def __init__(self, name, age): self.name = name self.age = age def speak(self): raise NotImplementedError("Subclasses must implement speak()") def describe(self): return f"{self.name} is {self.age} years old" def __repr__(self): return f"{type(self).__name__}(name={self.name!r})" class Dog(Animal): # Dog inherits from Animal def __init__(self, name, age, breed): super().__init__(name, age) # Call parent __init__ self.breed = breed def speak(self): # Override parent method return f"{self.name}: Woof!" def fetch(self, item): return f"{self.name} fetches the {item}!" class Cat(Animal): def speak(self): return f"{self.name}: Meow!" def purr(self): return f"{self.name} purrs..." rex = Dog("Rex", 3, "Labrador") whiskers = Cat("Whiskers", 5) print(rex.speak()) # Rex: Woof! print(whiskers.speak()) # Whiskers: Meow! print(rex.describe()) # Rex is 3 years old (inherited!) print(rex.fetch("ball")) # Rex fetches the ball!

isinstance() and issubclass()

isinstance(rex, Dog) # True isinstance(rex, Animal) # True โ€” Dog IS an Animal isinstance(rex, Cat) # False issubclass(Dog, Animal) # True issubclass(Dog, Cat) # False issubclass(Dog, object) # True โ€” everything inherits from object type(rex) == Dog # True type(rex) == Animal # False โ€” type() is strict

Polymorphism

Polymorphism means the same operation works on different types. Python uses "duck typing" โ€” if it looks like a duck and quacks, it's a duck.

animals = [Dog("Rex", 3, "Lab"), Cat("Whiskers", 5), Dog("Buddy", 2, "Beagle")] # Polymorphic: same method call, different behavior for animal in animals: print(animal.speak()) # Rex: Woof! # Whiskers: Meow! # Buddy: Woof! # Works because all have speak() โ€” no inheritance required! class Robot: def speak(self): return "Beep boop" things = [Dog("Rex", 3, "Lab"), Robot()] for thing in things: print(thing.speak()) # Works! Both have speak()

Abstract Base Classes

from abc import ABC, abstractmethod class Shape(ABC): # Abstract base class โ€” cannot be instantiated @abstractmethod def area(self) -> float: pass @abstractmethod def perimeter(self) -> float: pass def describe(self): # Concrete method โ€” inherited as-is return f"{type(self).__name__}: area={self.area():.2f}, perimeter={self.perimeter():.2f}" class Circle(Shape): def __init__(self, radius): self.radius = radius def area(self): import math return math.pi * self.radius ** 2 def perimeter(self): import math return 2 * math.pi * self.radius class Rectangle(Shape): def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height def perimeter(self): return 2 * (self.width + self.height) shapes = [Circle(5), Rectangle(4, 6)] for s in shapes: print(s.describe()) # Circle: area=78.54, perimeter=31.42 # Rectangle: area=24.00, perimeter=20.00

Multiple Inheritance and MRO

class Flyable: def fly(self): return f"{self.name} is flying" class Swimmable: def swim(self): return f"{self.name} is swimming" class Duck(Animal, Flyable, Swimmable): def speak(self): return f"{self.name}: Quack!" donald = Duck("Donald", 3) print(donald.fly()) # Donald is flying print(donald.swim()) # Donald is swimming print(donald.speak()) # Donald: Quack! # Method Resolution Order (MRO) โ€” which class wins? print(Duck.__mro__) # [Duck, Animal, Flyable, Swimmable, object]

Key Takeaways

Practice Exercises

  1. Create an Employee hierarchy: base Employee class, then Manager (has a team list) and Developer (has a list of skills). Add a pay() method that's overridden in subclasses.
  2. Create an abstract Vehicle class with abstract fuel_type() and range_km(). Implement Car, ElectricCar, and Bicycle.
  3. Write a function that takes a list of Shapes and returns total area. It should work with any Shape subclass.
โ† Classes and Objects