CodingNic

Object-Oriented Programming

Inheritance and Polymorphism

Object-Oriented Programming 20 min read

Inheritance and Polymorphism

Objectives

By the end of this chapter, you should be able to:

  • Build a subclass with extends that reuses a base class’s constructor and methods
  • Call the parent constructor with super()
  • Override a method in a subclass
  • Explain polymorphism: the same method call producing different behavior depending on the actual object’s class

💡 Why this matters: Real programs often have several kinds of “the same basic thing,” like different shapes, different payment types, or different game characters. Inheritance lets you write the shared behavior once. Polymorphism lets you treat all those different kinds the same way in your code, while each one still does its own thing.

Inheritance with extends

A base class holds behavior shared by everything built on top of it.

javascript
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    return `${this.name} makes a sound.`;
  }
}

A subclass reuses Animal with extends, and can override any method it needs to behave differently.

javascript
class Dog extends Animal {
  speak() {
    return `${this.name} barks.`;
  }
}

const rex = new Dog("Rex");
console.log(rex.speak());
// Rex barks.
console.log(rex instanceof Animal);
// true

Dog never redefined a constructor, so it automatically uses Animal’s. rex still gets a name, and rex instanceof Animal is true because a Dog is still an Animal, just a more specific one.

super(): Calling the Parent Constructor

If a subclass needs its own constructor, for extra properties, it must call super() first, which runs the parent class’s constructor.

javascript
class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  speak() {
    return `${this.name} barks.`;
  }
}

const rex = new Dog("Rex", "Labrador");
console.log(rex.speak());
// Rex barks.
console.log(rex.name, rex.breed);
// Rex Labrador
console.log(rex instanceof Dog, rex instanceof Animal);
// true true

super(name) calls Animal’s constructor with name, which sets this.name. Only after that can Dog’s constructor safely set this.breed. JavaScript requires super() to run before you touch this in a subclass constructor.

Polymorphism: Same Call, Different Behavior

Polymorphism means calling the same method name on different objects and getting behavior specific to each object’s actual class. Add a second subclass:

javascript
class Cat extends Animal {
  speak() {
    return `${this.name} meows.`;
  }
}

const animals = [new Dog("Rex"), new Cat("Whiskers"), new Animal("Generic")];

for (const animal of animals) {
  console.log(animal.speak());
}
// Rex barks.
// Whiskers meows.
// Generic makes a sound.

The loop calls animal.speak() the exact same way for every item, it never checks whether animal is a Dog, a Cat, or a plain Animal. Each object still runs its own version of speak(), because that’s the version living on its own class’s prototype (from lesson 1 and 2). The calling code stays simple, while each object handles its own behavior.

Try It

  1. Write a base class Shape with a method describe() that returns "A shape". Write subclasses Circle and Square that override describe() to return something specific to each.
  2. Give Circle a constructor that takes radius and calls super(), and give Square a constructor that takes side and calls super().
  3. Put one Circle and one Square in an array, loop over it, and call describe() on each. Confirm the output is different for each even though the method call looks identical.
  4. Add a third subclass and confirm the loop still works without changing the loop itself.

Recap

  • extends builds a subclass on top of a base class, reusing its constructor and methods unless they’re overridden.
  • super() calls the parent class’s constructor, and must run before a subclass constructor uses this.
  • Overriding a method in a subclass replaces the base class’s version for objects of that subclass.
  • Polymorphism means the same method call behaves differently depending on the object’s actual class, which lets calling code stay simple while each class handles its own details.

Next lesson: exercises that combine classes, constructors, static methods, encapsulation, inheritance, and polymorphism.