ReviseAlgo Logo

OOP Fundamentals

Inheritance

Hierarchical code reuse

Last Updated: June 25, 2026 20 min read

Inheritance is the OOP mechanism by which one class (the subclass or derived class) acquires the state variables and behaviors of another class (the superclass or base class). It establishes an "Is-A" relationship, facilitating structured code reuse.

1. Learning Objectives

  • Establish hierarchical relationships using base and derived classes.
  • Understand constructor chaining and class execution order.
  • Differentiate between the structural implications of Inheritance vs Composition.

2. Problem Statement

Without inheritance, modeling different types of objects in the same domain leads to massive duplication. If you build an Employee Payroll System, you would copy-paste fields like id, name, and salary across FullTimeEmployee, PartTimeEmployee, and Contractor classes, multiplying technical debt.

3. Real-world Analogy

Think of a classification hierarchy of vehicles.

A Vehicle is the base concept (has speed, carries cargo). A Car is a subclass of Vehicle: it inherits speed controls but adds car-specific details (four passenger seats, windshield wipers). A SportsCar is a subclass of Car: it inherits passenger capacities but adds sports performance details (turbochargers, carbon fiber spoilers).

4. Theory

Inheritance defines how properties cascade down parent-child boundaries:

  • Superclass (Base Class): Contains shared states and routines.
  • Subclass (Derived Class): Inherits public/protected members, and can override behaviors or add properties.
  • Constructor Chaining: When instantiating a subclass, the parent constructor executes first (using super() in Java) to initialize inherited attributes.
  • Single vs Multiple Inheritance: Java restricts classes to single inheritance to prevent the Diamond Problem (resolving conflicts when inheriting identical methods from two parents). C++ supports multiple inheritance directly.

5. Visual Diagrams (UML & Memory structures)

Class Diagram

Employee
# name: String
# baseSalary: double
+ calculatePay(): double
▲ Inherits (Is-A)
FullTimeEmployee
- bonus: double
+ calculatePay() [override]

Object Diagram

emp: FullTimeEmployee
name = "Alice" (inherited)
baseSalary = 5000.00 (inherited)
bonus = 1000.00

Memory Diagram

Stack (Reference)

Employee empRef = @0x4d5e
points to single composite allocation

Heap space (Subclass Object Layout)

@0x4d5e:
Type: FullTimeEmployee

[Parent fields]
name: "Alice"
baseSalary: 5000.00

[Child fields]
bonus: 1000.00

Object Lifecycle

1. Subclass constructor invoked
2. Superclass constructor executes (super())
3. Subclass initialization block executes

6. Syntax Explanation

  • Java: Uses extends to establish inheritance. Accesses parent constructor using super(...).
  • Python: Passes the base class name inside subclass parameters: class FullTimeEmployee(Employee):. Calls parent constructor via super().__init__(...).
  • C++: Declares accessibility namespaces during inheritance: class FullTimeEmployee : public Employee. Passes variables up to base constructors inside initialization lists.

7. Step-by-Step Implementation

Let's build a hierarchical Employee Payroll System:

  • Step 1: Declare base class Employee with protected variables name and baseSalary.
  • Step 2: Declare a constructor initializing both base variables.
  • Step 3: Build a subclass FullTimeEmployee extending Employee and declaring a subclass field bonus.
  • Step 4: Invoke super(...) inside the subclass constructor to link instantiation.
  • Step 5: Override the calculatePay() method inside the subclass to combine salary and bonus values.

8. Complete Code (Mini Project)

9. Code Walkthrough

FullTimeEmployee inherits name and baseSalary properties from the base class Employee. During initialization, super(name, baseSalary) runs the parent constructor. The @Override annotation flags the compiler to route calculations to the child's method at runtime.

10. Execution Flow

  • Call subclass constructor.
  • Trigger base parent class constructor to map base variables on the heap.
  • Subclass constructor binds child attributes.
  • Call calculatePay(), yielding combined values polymorphically.

11. Internal Working

In memory, the subclass object does not contain two nested instances. The JVM allocates one flat composite memory block in the Heap that contains both the parent's fields (name, baseSalary) and the child's fields (bonus).

12. Complexity Analysis

  • Time Complexity: $O(1)$ to instantiate objects and access fields.
  • Space Complexity: $O(1)$ constant allocation per object.

13. Best Practices

  • Favor Composition over Inheritance: Use inheritance only when a strict, permanent "Is-A" relationship is present. Otherwise, use composition ("Has-A").
  • Keep hierarchies shallow: Keep class hierarchies to 2 or 3 levels maximum. Deep hierarchies are difficult to maintain.

14. Common Mistakes

  • Violating the Liskov Substitution Principle (LSP) by changing the expected behavior of base methods in a way that breaks client code.
  • Inheriting from a class just to reuse its helper methods when no conceptual "Is-A" link exists.

15. Interview Questions

Q: What is the Diamond Problem, and how does Java avoid it?
Answer: The Diamond Problem occurs in multiple inheritance when a class inherits from two classes that both inherit from a single base class. If both parent classes override a method, the subclass doesn't know which one to run. Java avoids this by supporting only single class inheritance.

16. Practice Exercises

  • Easy: Add a subclass Contractor that calculates pay based on hours worked and an hourly rate.
  • Medium: Add validation inside the Employee constructor to prevent null names or negative base salaries. Ensure this validation runs when subclasses are instantiated.
  • Hard: Redesign the system to calculate pay using composition (a PayrollStrategy class injected at runtime) instead of class inheritance, comparing the trade-offs of both designs.

17. Challenge Problem

Design a vehicle rental hierarchy (VEHICLE base, CAR child, TRUCK child) with dynamic surcharge computations based on vehicle weight and dimensions.

18. Summary

  • Inheritance establishes an "Is-A" relationship between classes.
  • Constructor chaining ensures parent attributes are initialized before subclass execution.
  • Subclasses are stored as flat, single objects containing both parent and child fields in heap memory.

19. Cheat Sheet

Relationship Type Conceptual Link Coupling Level
Inheritance Is-A relationship (SportsCar is a Car) Tightly Coupled
Composition Has-A relationship (Car has an Engine) Loosely Coupled

20. Quiz

1. Which relationship type represents class inheritance?

A) Has-A
B) Is-A (Correct)
C) Uses-A

2. Which constructor runs first when instantiating a subclass?

A) Subclass constructor
B) Superclass constructor (Correct)
C) Constructors run in parallel threads

3. How does Java resolve the Diamond Problem in multiple class inheritance?

A) Using interfaces instead of abstract classes
B) Restricting class extension to single inheritance only (Correct)
C) By picking the first class declared in the classpath

4. What is constructor chaining?

A) Calling a constructor from within another constructor (Correct)
B) Executing destructors recursively
C) Re-instantiating null pointers

5. How are parent and child fields laid out in heap memory when instantiating a subclass?

A) Allocated in two separate heap blocks pointing to each other
B) Allocated in a single flat memory block containing both parent and child fields (Correct)
C) Allocated inside stack frames

6. What keyword is used in Java subclasses to call parent methods or constructors?

A) base
B) super (Correct)
C) this

7. What is the access modifier that grants access only to subclasses and the package?

A) private
B) protected (Correct)
C) default

8. Which OOP rule requires subclass objects to be substitute-able for base parent objects?

A) Single Responsibility Principle
B) Liskov Substitution Principle (Correct)
C) Dependency Inversion Principle

9. In C++, why must base class destructors be declared virtual?

A) To prevent memory leaks when deleting subclass objects via base pointers (Correct)
B) To speed up program termination checks
C) To enable multi-inheritance

10. What does subclass method overriding replace?

A) The parent method signature
B) The execution of the parent method at runtime (Correct)
C) The compile checks

21. Next Lesson Preview

In the next lesson, we will explore Polymorphism to master both compile-time method overloading and runtime method overriding!