JavaScript - Inheritance

Hello there, future JavaScript wizards! Today, we're going to embark on an exciting journey through the magical world of inheritance in JavaScript. Don't worry if you're new to programming; I'll be your friendly guide, and we'll explore this concept step by step. So, grab your virtual wands (keyboards), and let's dive in!

JavaScript - Inheritance

Inheritance in JavaScript

Inheritance is like passing down family traits, but in the world of programming. Imagine you're creating a family tree of objects, where children can inherit properties and methods from their parents. Cool, right?

Let's start with a simple example:

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

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

class Dog extends Animal {
  bark() {
    console.log(`${this.name} barks: Woof woof!`);
  }
}

const myDog = new Dog("Buddy");
myDog.speak(); // Output: Buddy makes a sound.
myDog.bark();  // Output: Buddy barks: Woof woof!

In this example, Dog inherits from Animal. This means Dog gets all the properties and methods of Animal, plus its own unique method bark(). It's like Buddy inheriting the ability to speak from all animals, but also having his special barking superpower!

JavaScript Single Class Inheritance

Single class inheritance is when a class inherits from just one parent class. It's like having one super cool parent you want to learn everything from.

Here's another example:

class Vehicle {
  constructor(brand) {
    this.brand = brand;
  }

  start() {
    console.log(`Starting the ${this.brand}.`);
  }
}

class Car extends Vehicle {
  honk() {
    console.log(`${this.brand} car goes beep beep!`);
  }
}

const myCar = new Car("Toyota");
myCar.start(); // Output: Starting the Toyota.
myCar.honk();  // Output: Toyota car goes beep beep!

Here, Car is inheriting from Vehicle. It's like your car learning how to start from the general concept of vehicles, but also knowing how to honk because, well, it's a car!

JavaScript super() Keyword

Now, let's talk about the super() keyword. It's like a respectful nod to your parents, acknowledging their contribution to your awesomeness.

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

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // Calling the parent constructor
    this.breed = breed;
  }

  introduce() {
    console.log(`I'm ${this.name}, a ${this.breed} dog.`);
  }
}

const myDog = new Dog("Max", "Labrador");
myDog.introduce(); // Output: I'm Max, a Labrador dog.

The super(name) call in the Dog constructor is like saying, "Hey Animal parent, can you handle setting up the name for me?" It's a way of reusing the parent's constructor logic.

JavaScript Multilevel Inheritance

Multilevel inheritance is like a family tree with multiple generations. Let's see an example:

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

  eat() {
    console.log(`${this.name} is eating.`);
  }
}

class Dog extends Animal {
  bark() {
    console.log(`${this.name} says woof!`);
  }
}

class Labrador extends Dog {
  swim() {
    console.log(`${this.name} is swimming.`);
  }
}

const myDog = new Labrador("Charlie");
myDog.eat();  // Output: Charlie is eating.
myDog.bark(); // Output: Charlie says woof!
myDog.swim(); // Output: Charlie is swimming.

Here, Labrador inherits from Dog, which inherits from Animal. It's like Charlie the Labrador learning to eat from all animals, to bark from dogs, and having his own special swimming ability.

JavaScript Hierarchical Inheritance

Hierarchical inheritance is when multiple classes inherit from a single parent class. It's like siblings inheriting traits from the same parent.

class Vehicle {
  constructor(brand) {
    this.brand = brand;
  }

  start() {
    console.log(`Starting the ${this.brand}.`);
  }
}

class Car extends Vehicle {
  drive() {
    console.log(`Driving the ${this.brand} car.`);
  }
}

class Motorcycle extends Vehicle {
  wheelie() {
    console.log(`Doing a wheelie on the ${this.brand} motorcycle!`);
  }
}

const myCar = new Car("Toyota");
const myBike = new Motorcycle("Harley");

myCar.start();    // Output: Starting the Toyota.
myCar.drive();    // Output: Driving the Toyota car.

myBike.start();   // Output: Starting the Harley.
myBike.wheelie(); // Output: Doing a wheelie on the Harley motorcycle!

Both Car and Motorcycle inherit from Vehicle, but they each have their unique methods.

Inheriting Static Members of the Class

Static members belong to the class itself, not to instances. But they can still be inherited! Let's see how:

class MathOperations {
  static PI = 3.14159;

  static calculateCircleArea(radius) {
    return this.PI * radius * radius;
  }
}

class AdvancedMath extends MathOperations {
  static calculateSphereVolume(radius) {
    return (4/3) * this.PI * radius * radius * radius;
  }
}

console.log(AdvancedMath.PI); // Output: 3.14159
console.log(AdvancedMath.calculateCircleArea(5)); // Output: 78.53975
console.log(AdvancedMath.calculateSphereVolume(3)); // Output: 113.09733

Here, AdvancedMath inherits the static PI property and calculateCircleArea method from MathOperations.

JavaScript Prototype Based Inheritance

Before ES6 classes, JavaScript used prototype-based inheritance. It's a bit trickier, but still important to understand:

function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  console.log(`${this.name} makes a sound.`);
};

function Dog(name) {
  Animal.call(this, name);
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log(`${this.name} barks: Woof woof!`);
};

const myDog = new Dog("Rex");
myDog.speak(); // Output: Rex makes a sound.
myDog.bark();  // Output: Rex barks: Woof woof!

This achieves the same result as our first class-based example, but using the older prototype syntax.

Benefits of Inheritance

Inheritance in JavaScript offers several advantages:

  1. Code Reusability
  2. Extensibility
  3. Maintainability
  4. Polymorphism

Here's a table summarizing these benefits:

Benefit Description
Code Reusability Inherit properties and methods from parent classes, reducing duplication
Extensibility Easily add new features to existing classes
Maintainability Changes in parent classes automatically reflect in child classes
Polymorphism Use objects of different classes through the same interface

Remember, with great power comes great responsibility. Use inheritance wisely, and your code will thank you!

And there you have it, folks! We've journeyed through the land of JavaScript inheritance. I hope this guide has illuminated the path for you. Keep practicing, stay curious, and happy coding!

Credits: Image by storyset