Inheritance & Polymorphism
Build classes on top of other classes with extends and super, override methods, and let one interface work for many types.
Inheritance lets a class build on another: a subclass gets the parent's properties and methods, then adds or changes what it needs. Polymorphism means many different classes can respond to the same method call in their own way — so code that uses the interface doesn't care about the concrete type.
class Animal {
constructor(name) { this.name = name; }
speak() { return `${this.name} makes a sound`; }
}
class Dog extends Animal {
speak() { // override the parent's method
return `${this.name} barks`;
}
}
class Cat extends Animal {
speak() { return `${this.name} meows`; }
}
console.log(new Dog('Rex').speak());
console.log(new Cat('Lu').speak());extends sets up the parent-child link; each subclass overrides speak() with its own version. When a subclass constructor needs to run the parent's setup, it calls super(...) first.
#Polymorphism in action
class Animal {
constructor(name) { this.name = name; }
speak() { return `${this.name} makes a sound`; }
}
class Dog extends Animal { speak() { return `${this.name} barks`; } }
class Cat extends Animal { speak() { return `${this.name} meows`; } }
const zoo = [new Dog('Rex'), new Cat('Lu'), new Animal('Thing')];
for (const a of zoo) {
console.log(a.speak()); // each responds in its own way
}Program to the shared interface
The loop above never checks if (a instanceof Dog). It just calls a.speak() and trusts each object to do the right thing. That's the power of polymorphism — you can add a new Bird class later and the loop works unchanged.
What does calling `speak()` on a `Dog` that overrides it do?
Key takeaways
- `class Dog extends Animal` makes Dog inherit Animal's members.
- A subclass can override a method by redefining it; `super.method()` calls the parent's version.
- `super(...)` in a subclass constructor runs the parent constructor (call it before using `this`).
- Polymorphism: many classes implement the same method, so shared code calls it without knowing the concrete type.
What does this print?
class A { greet() { return 'A'; } }
class B extends A { greet() { return 'B'; } }
console.log(new B().greet());This subclass constructor throws "Must call super constructor". Fix?
class Animal { constructor(name){ this.name = name; } }
class Dog extends Animal {
constructor(name) {
this.legs = 4;
super(name);
}
}Complete the line so the subclass extends Shape.
class Circle Shape { area() { return 3.14 * this.r ** 2; } }
Make a Square class extend a Shape class. Shape has area() returning 0; Square (constructed with side) overrides area() to return side * side. new Square(4).area() should be 16.
Try it live — edit the code and hit Run to see the output: