Javascript OOP: Class Inheritance Tutorial

In this Javascript tutorial we learn how to inherit functionality from one class to another without rewriting any code.

We also learn how to inherit constructor functionality into child classes with the super() constructor.

What is class inheritance

Inheritance allows us to define a class that acts as a sub, or child class, and inherits functionality from another class, known as a base, parent, or super class.

Inheritance is referred to as an Is-A type relationship between classes. For example, a cat is an animal, or a car is a vehicle.

Inheritance makes it possible to reuse code from another class. We wrap common code in one class, then reuse that code in a child class which can extend the functionality.

Inheritance also provides us with polymorphic behavior, which can be quite powerful.

How to create a child (sub) class

To create a class that inherits from another, we use the extends keyword.

Syntax:
class ParentClass {

}

class ChildClass extends ParentClass {

}

When we inherit from a parent class, the child class will receive all the properties and methods that the parent class has.

Example:
<script>

  class Animal {

    move() {
      document.write("<p>Animal parent class. Move...</p>");
    }
  }

  class Dog extends Animal {

    growl() {
      document.write("<p>Dog child class. A dog can growl, but a duck can't. Grrr...</p>");
    }
  }

  class Duck extends Animal {

    quack() {
      document.write("<p>Duck Child class. A duck can quack, but a dog can't. Quack...</p>");
    }
  }

  var fluffy = new Dog();
  var donald = new Duck();

  // The Dog child class has access to
  // everything in the main class
  fluffy.move();
  // as well as its own functionality
  fluffy.growl();

  donald.move();
  donald.quack();

</script>

In the example above, we create two child classes, Dog & Duck, that inherit from the parent class Animal.

All types of animals can move in some capacity, so it’s included in the parent class. Any child class that inherit from animal, will have the move functionality available to it.

Child classes have more specific functionality that won’t make sense in the parent class, such as growling, because not all animals can growl.

As another example, consider an online forum. Users of the forum typically have different roles, such as member, moderator and administrator.

  • A member, moderator and administrator may create posts.
  • A moderator and administrator may move posts to other categories, but a member can’t.
  • An administrator may create categories, but a moderator and member can’t.

So, the parent class could include the functionality to create posts, so as to be available to all roles. Child classes would be used to add functionality for different roles.

How to inherit contructor functionality with super

If a child class doesn’t have its own constructor, we can use the constructor of the parent class as we normally would.

Example:
<script>

  class Animal {

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

  class Dog extends Animal {

    growl() {
      document.write("<p>Dog child class. A dog can growl, but a duck can't. Grrr...</p>");
    }
  }

  var dog_1 = new Dog("Fluffy");

  document.write("My dog's name is ", dog_1.name);

</script>

But, when a child class has its own constructor, we need to add the functionality from the parent class constructor, into the child class constructor.

Example:
<script>

  class Animal {

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

  class Dog extends Animal {

    constructor(is_good_boy) {

      this.is_good_boy = is_good_boy;
    }

    growl() {

      if (is_good_boy) {
        document.write("<p>", name, " doesn't growl, he's a good boy</p>");
      } else {
        document.write("<p>Grrrrr....</p>");
      }
    }
  }

  var dog_1 = new Dog("Fluffy");

  document.write("My dog's name is ", dog_1.name);

</script>

In the example above, we’ve added a constructor in the child class. We then try to access the name property from the parent class again, but this time the translator raises an error.

Output:
Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

The error means we have to bring everything from the parent constructor into the child constructor before we can access it. We do this with super().

We can think of super as a regular function call, with super being the function name. It also uses all the parameters of the parent class constructor.

Example:
<script>

  class Animal {

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

  class Dog extends Animal {

    constructor(name, is_good_boy) {

      super(name);
      this.is_good_boy = is_good_boy;
    }

    growl() {

      if (is_good_boy) {
        document.write("<p>", name, " doesn't growl, he's a good boy</p>");
      } else {
        document.write("<p>Grrrrr....</p>");
      }
    }
  }

  var dog_1 = new Dog("Fluffy", true);

  document.write("My dog's name is ", dog_1.name);

</script>

In the example above, we simply call super() in the child class’s constructor. Because the parent class has a parameter, super also needs a parameter so we add one to the child class constructor.

Summary: Points to remember

  • Inheritance allows one class to inherit functionality from another without rewriting the same code.
  • We use the extends keyword to indicate that one class inherits from another.
  • The child class will automatically receive all the functionality from the parent class unless it contains its own constructor.
  • We inherit constructor functionality with the super() constructor.
    • If the parent class constructor has any parameters, the super() constructor will need the same parameters.