#1 Data Analytics Program in India
₹2,499₹1,499Enroll Now
7 min read
•Question 19 of 41medium

Inheritance 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())  # New

The 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}))   # 1

isinstance() 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))   # True

Interview Tip

When asked about inheritance and polymorphism:

  1. Inheritance: child class gets parent's attributes/methods
  2. super() calls parent methods, follows MRO
  3. MRO: left-to-right, depth-first order
  4. ABC for abstract classes with @abstractmethod
  5. Duck typing: behavior matters, not type
  6. isinstance() checks type, issubclass() checks inheritance