Skip to content

Inheritance

Inheritance is a mechanism that allows a class (child/derived class) to inherit properties and methods from another class (parent/base class). It’s one of the four pillars of OOP and enables code reuse and hierarchical relationships.

  • To reuse code without duplication
  • To create hierarchical relationships between classes (IS-A relationship)
  • To enable polymorphism through shared interfaces
  • To create specialized versions of general concepts
  • To avoid rewriting common code in multiple classes
  • To model real-world hierarchical relationships (Dog IS-A Animal)
  • To create extensible frameworks and libraries
  • To implement the Open/Closed Principle (open for extension, closed for modification)

Children inherit traits from their parents:

  • Parents provide a genetic blueprint (eye color, height, certain behaviors)
  • Children get all these traits automatically
  • Children can also have their own unique traits
  • Children can override inherited traits (e.g., dye their hair a different color)

A child IS-A descendant of their parent — the same type of relationship exists with class inheritance.


Inheritance is the mechanism where a new class is derived from an existing class. The derived class automatically contains all non-private properties and methods of the base class, and can add new members or override existing ones.


Without inheritance:

// ❌ Without inheritance — duplicated code
class Dog {
constructor(name) { this.name = name; }
eat() { console.log(`${this.name} is eating`); }
sleep() { console.log(`${this.name} is sleeping`); }
bark() { console.log(`${this.name} barks`); }
}
class Cat {
constructor(name) { this.name = name; }
eat() { console.log(`${this.name} is eating`); } // Duplicate!
sleep() { console.log(`${this.name} is sleeping`); } // Duplicate!
meow() { console.log(`${this.name} meows`); }
}

With inheritance:

// ✅ With inheritance — shared code in parent
class Animal {
constructor(name) { this.name = name; }
eat() { console.log(`${this.name} is eating`); }
sleep() { console.log(`${this.name} is sleeping`); }
}
class Dog extends Animal {
bark() { console.log(`${this.name} barks`); }
}
class Cat extends Animal {
meow() { console.log(`${this.name} meows`); }
}

classDiagram
class Animal {
+name: string
+eat() void
+sleep() void
}
class Dog {
+breed: string
+bark() void
+fetch() void
}
class Cat {
+color: string
+meow() void
+scratch() void
}
class Labrador {
+retrieve() void
}
Animal <|-- Dog : extends
Animal <|-- Cat : extends
Dog <|-- Labrador : extends

Inheritance can be categorized into several types. Click here to explore each type in detail →

TypeDescriptionSupportExample
SingleOne child, one parentAll OOP languagesDog extends Animal
MultilevelChain of inheritanceAll OOP languagesA → B → C
HierarchicalMany children, one parentAll OOP languagesAnimal → Dog, Cat, Bird
MultipleOne child, many parentsPython, C++Duck extends Animal, Flyable
HybridCombinationC++Rarely used

class Vehicle {
constructor(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
start() {
console.log(`${this.make} ${this.model} is starting...`);
}
stop() {
console.log(`${this.make} ${this.model} is stopping...`);
}
getInfo() {
return `${this.year} ${this.make} ${this.model}`;
}
}
class Car extends Vehicle {
constructor(make, model, year, doors) {
super(make, model, year); // Call parent constructor
this.doors = doors;
}
honk() {
console.log("Beep beep!");
}
// Override parent method
getInfo() {
return `${super.getInfo()} — ${this.doors} doors`;
}
}
class ElectricCar extends Car {
constructor(make, model, year, doors, batteryRange) {
super(make, model, year, doors);
this.batteryRange = batteryRange;
}
// Override
start() {
console.log(`⚡ ${this.make} ${this.model} is starting silently...`);
}
charge() {
console.log("Charging battery...");
}
}
const tesla = new ElectricCar("Tesla", "Model 3", 2024, 4, 358);
console.log(tesla.getInfo()); // "2024 Tesla Model 3 — 4 doors"
tesla.start(); // "⚡ Tesla Model 3 is starting silently..."
tesla.charge(); // "Charging battery..."
tesla.stop(); // "Tesla Model 3 is stopping..."

  • Favor composition over inheritance — “Has-a” is often better than “is-a”
  • Keep inheritance hierarchies shallow — 3-4 levels max
  • Follow the Liskov Substitution Principle — child should be substitutable for parent
  • Use inheritance for behavior, not just code reuse
  • Make base classes abstract if they shouldn’t be instantiated
  • Document overridden methods — super() calls included

  • Deep inheritance chains — Hard to understand and maintain
  • Breaking LSP — Child class that doesn’t behave like parent
  • Overusing inheritance for code reuse — composition is usually better
  • Calling overridable methods in constructors — May call child method before child is initialized
  • Misusing super — Forgetting to call parent constructor

ConceptKey Point
InheritanceChild class extends parent class (IS-A)
BenefitsCode reuse, hierarchical modeling, polymorphism
TypesSingle, Multilevel, Hierarchical, Multiple, Hybrid
superAccess parent class constructor and methods
OverrideChild redefines parent method
Rule of ThumbPrefer composition unless IS-A is clearly satisfied

Previous Topic: Abstraction → Next Topic: Super Keyword → Related Topics: Types of Inheritance, Method Overriding