Inheritance

Part of Object-Oriented Programming

What is Inheritance?

Inheritance is one of the four pillars of OOP. It allows a class to inherit attributes and methods from another class, promoting code reuse and establishing a hierarchical relationship between classes.

The class that inherits is called the child class(or derived/subclass), and the class being inherited from is the parent class (or base/superclass).

Real-World Analogy

Think of biological inheritance: children inherit traits from their parents (eye color, hair type) but also develop their own unique characteristics. Similarly, a Dog class inherits from Animal (can eat, sleep) but adds its own abilities (bark, fetch).

Interactive Visualization

Inheritance Hierarchy

AnimalParent
+ name, age
+ eat(), sleep()
DogChild
+ breed
+ bark(), fetch()
CatChild
+ indoor
+ meow(), scratch()
Key Concept: Child classes (Dog, Cat) inherit all attributes and methods from the parent class (Animal) and can add their own unique members.

Types of Inheritance

Single Inheritance

A class inherits from one parent class only.

Dog → Animal

Multiple Inheritance

A class inherits from multiple parent classes. (Python, C++)

FlyingFish → Fish, Bird

Multilevel Inheritance

A chain of inheritance (grandparent → parent → child).

Puppy → Dog → Animal

Hierarchical Inheritance

Multiple classes inherit from a single parent.

Dog, Cat, Bird → Animal

Code Implementation

# Inheritance in Python
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def eat(self):
        return f"{self.name} is eating"
    
    def sleep(self):
        return f"{self.name} is sleeping"

# Dog inherits from Animal
class Dog(Animal):
    def __init__(self, name, age, breed):
        super().__init__(name, age)  # Call parent constructor
        self.breed = breed
    
    def bark(self):
        return f"{self.name} says Woof!"
    
    def fetch(self):
        return f"{self.name} is fetching the ball"

# Cat inherits from Animal
class Cat(Animal):
    def __init__(self, name, age, indoor=True):
        super().__init__(name, age)
        self.indoor = indoor
    
    def meow(self):
        return f"{self.name} says Meow!"

# Using inheritance
dog = Dog("Buddy", 3, "Golden Retriever")
print(dog.eat())    # Inherited: Buddy is eating
print(dog.bark())   # Own method: Buddy says Woof!
print(dog.breed)    # Own attribute: Golden Retriever

cat = Cat("Whiskers", 2)
print(cat.sleep())  # Inherited: Whiskers is sleeping
print(cat.meow())   # Own method: Whiskers says Meow!

Method Overriding

Child classes can override parent methods to provide their own implementation:

class Animal:
    def speak(self):
        return "Some sound"

class Dog(Animal):
    def speak(self):  # Override parent method
        return "Woof!"

class Cat(Animal):
    def speak(self):  # Override parent method
        return "Meow!"

# Polymorphism in action
animals = [Dog(), Cat(), Animal()]
for animal in animals:
    print(animal.speak())
# Output: Woof! Meow! Some sound

Common Mistakes

Forgetting to call super().__init__()

If you define a constructor in the child class, you must call the parent's constructor to initialize inherited attributes.

Deep inheritance hierarchies

Avoid inheritance chains more than 2-3 levels deep. It becomes hard to track where methods come from. Prefer composition over deep inheritance.

Inheriting just for code reuse

Use inheritance for "is-a" relationships (Dog is an Animal), not just to reuse code. For "has-a" relationships, use composition instead.

Interview Tips

Q:"When would you use inheritance vs composition?"
A:"Use inheritance for 'is-a' relationships (Car is a Vehicle). Use composition for 'has-a' relationships (Car has an Engine). Composition is more flexible and preferred when the relationship isn't clearly hierarchical."

Test Your Knowledge

Inheritance Quiz

Question 1 of 6

What is inheritance in OOP?