7 min read
ā¢Question 19 of 41mediumInheritance and Polymorphism
Advanced OOP concepts.
What You'll Learn
- Single and multiple inheritance
- Method Resolution Order (MRO)
- Using super() correctly
- Abstract base classes
- Polymorphism and duck typing
Understanding Inheritance
Inheritance allows a class to inherit attributes and methods from another class. The child class can override or extend parent behavior.
code.pyPython
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "Some sound"
class Dog(Animal):
def speak(self): # Override parent method
return f"{self.name} says Woof!"
def fetch(self): # New method
return f"{self.name} is fetching"
dog = Dog("Buddy")
print(dog.name) # Inherited
print(dog.speak()) # Overridden
print(dog.fetch()) # NewThe super() Function
code.pyPython
class Parent:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, I'm {self.name}"
class Child(Parent):
def __init__(self, name, age):
super().__init__(name) # Call parent constructor
self.age = age
def greet(self):
parent_greeting = super().greet() # Call parent method
return f"{parent_greeting}, age {self.age}"
child = Child("Alice", 10)
print(child.greet()) # "Hello, I'm Alice, age 10"Multiple Inheritance
code.pyPython
class A:
def method(self):
return "A"
class B:
def method(self):
return "B"
class C(A, B): # Inherits from both
pass
class D(B, A): # Different order
pass
c = C()
d = D()
print(c.method()) # "A" (first in MRO)
print(d.method()) # "B" (first in MRO)Method Resolution Order (MRO)
code.pyPython
class A:
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
# MRO determines method lookup order
print(D.__mro__)
# (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)
# Use mro() method
print(D.mro())Abstract Base Classes
code.pyPython
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
"""Calculate area - must be implemented."""
pass
@abstractmethod
def perimeter(self):
"""Calculate perimeter - must be implemented."""
pass
def description(self):
"""Concrete method - can be inherited."""
return f"Area: {self.area()}, Perimeter: {self.perimeter()}"
# shape = Shape() # TypeError: Can't instantiate abstract class
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)
rect = Rectangle(4, 5)
print(rect.area()) # 20
print(rect.description()) # "Area: 20, Perimeter: 18"Polymorphism
Same interface, different implementations:
code.pyPython
class Dog:
def speak(self):
return "Woof!"
class Cat:
def speak(self):
return "Meow!"
class Duck:
def speak(self):
return "Quack!"
def animal_sound(animal):
# Works with any object that has speak() method
return animal.speak()
animals = [Dog(), Cat(), Duck()]
for animal in animals:
print(animal_sound(animal))
# Woof! Meow! Quack!Duck Typing
"If it walks like a duck and quacks like a duck..."
code.pyPython
class Car:
def speak(self): # Not an animal, but has speak()
return "Vroom!"
# Works because it has the method, not because of inheritance
print(animal_sound(Car())) # "Vroom!"
# Python cares about behavior, not type
def get_length(obj):
return len(obj) # Works with any object that has __len__
print(get_length([1, 2, 3])) # 3
print(get_length("hello")) # 5
print(get_length({"a": 1})) # 1isinstance() and issubclass()
code.pyPython
class Animal:
pass
class Dog(Animal):
pass
dog = Dog()
print(isinstance(dog, Dog)) # True
print(isinstance(dog, Animal)) # True (parent class)
print(isinstance(dog, object)) # True (everything is object)
print(issubclass(Dog, Animal)) # True
print(issubclass(Dog, object)) # TrueInterview Tip
When asked about inheritance and polymorphism:
- Inheritance: child class gets parent's attributes/methods
- super() calls parent methods, follows MRO
- MRO: left-to-right, depth-first order
- ABC for abstract classes with @abstractmethod
- Duck typing: behavior matters, not type
- isinstance() checks type, issubclass() checks inheritance