In object-oriented programming (OOP), inheritance is a fundamental concept that allows one class to inherit properties and methods from another. This promotes code reusability, reduces redundancy, and helps in creating a hierarchical relationship between classes. In JavaScript, inheritance is achieved using the extends keyword along with the super keyword.
In this tutorial, you'll learn how to use these keywords to create parent-child relationships between classes and understand their practical implications.
Class inheritance allows you to define a base class (parent) with common properties and methods, and then extend it to create derived classes (children). The child classes can inherit all the features of the parent class and also add or override them as needed. This is particularly useful in scenarios where multiple classes share similar functionalities but have some unique characteristics.
Understanding how to implement inheritance in JavaScript is crucial for building scalable and maintainable applications, especially when dealing with complex systems that require a structured hierarchy.
extends KeywordThe extends keyword is used to create a subclass (child class) from an existing class (parent class). The syntax is straightforward:
1class ParentClass {2// Parent class methods and properties3}45class ChildClass extends ParentClass {6// Child class methods and properties7}
Let's start with a simple example where we have a Vehicle class as the parent and a Car class as the child.
1class Vehicle {2constructor(name) {3this.name = name;4}56drive() {7console.log(`${this.name} is driving.`);8}9}1011class Car extends Vehicle {12// No additional properties or methods for now13}1415const myCar = new Car('Toyota');16myCar.drive(); // Output: Toyota is driving.
Toyota is driving.
In this example, the Car class inherits the name property and the drive method from the Vehicle class. When we create a new instance of Car, it can use the inherited drive method.
super KeywordThe super keyword is used in two main contexts within child classes:
super to Call Parent ConstructorLet's extend our previous example by adding a new property and method to the Car class, and use super to call the parent constructor.
1class Vehicle {2constructor(name) {3this.name = name;4}56drive() {7console.log(`${this.name} is driving.`);8}9}1011class Car extends Vehicle {12constructor(name, model) {13super(name); // Call the parent constructor14this.model = model;15}1617displayInfo() {18console.log(`${this.name} (${this.model}) is driving.`);19}20}2122const myCar = new Car('Toyota', 'Corolla');23myCar.displayInfo(); // Output: Toyota (Corolla) is driving.
Toyota (Corolla) is driving.
In this example, the Car class has an additional property model. The constructor of the Car class calls super(name) to initialize the name property inherited from the Vehicle class. This ensures that all properties are properly initialized.
super to Access Parent MethodsNow, let's override the drive method in the Car class and use super to call the parent class's drive method.
1class Vehicle {2constructor(name) {3this.name = name;4}56drive() {7console.log(`${this.name} is driving.`);8}9}1011class Car extends Vehicle {12constructor(name, model) {13super(name);14this.model = model;15}1617drive() {18super.drive(); // Call the parent class's drive method19console.log(`The car is also a ${this.model}.`);20}21}2223const myCar = new Car('Toyota', 'Corolla');24myCar.drive();25// Output:26// Toyota is driving.27// The car is also a Corolla.
Toyota is driving. The car is also a Corolla.
In this example, the drive method in the Car class calls super.drive() to execute the drive method from the Vehicle class. This allows us to extend the functionality of the inherited method without completely replacing it.
Let's create a more complex example where we have a base Animal class and two derived classes, Dog and Cat, each with their own unique methods.
1class Animal {2constructor(name) {3this.name = name;4}56speak() {7console.log(`${this.name} makes a sound.`);8}9}1011class Dog extends Animal {12constructor(name, breed) {13super(name);14this.breed = breed;15}1617speak() {18super.speak();19console.log(`The dog barks.`);20}2122fetch() {23console.log(`${this.name} is fetching the ball.`);24}25}2627class Cat extends Animal {28constructor(name, color) {29super(name);30this.color = color;31}3233speak() {34super.speak();35console.log(`The cat meows.`);36}3738purr() {39console.log(`${this.name} is purring.`);40}41}4243const myDog = new Dog('Buddy', 'Golden Retriever');44myDog.speak(); // Output: Buddy makes a sound. The dog barks.45myDog.fetch(); // Output: Buddy is fetching the ball.4647const myCat = new Cat('Whiskers', 'Black');48myCat.speak(); // Output: Whiskers makes a sound. The cat meows.49myCat.purr(); // Output: Whiskers is purring.
Buddy makes a sound. The dog barks. Buddy is fetching the ball. Whiskers makes a sound. The cat meows. Whiskers is purring.
In this example, we have an Animal class with a generic speak method. The Dog and Cat classes extend Animal and override the speak method to provide specific behaviors. Each derived class also has its own unique methods (fetch for Dog and purr for Cat). This demonstrates how inheritance can be used to create a clear hierarchy of related classes.
extends keyword.super keyword is used to call the parent constructor and access parent methods within child classes.Understanding these concepts will help you design more organized and maintainable JavaScript applications. By leveraging inheritance effectively, you can create complex systems with minimal redundancy.
In the next tutorial, we'll explore JavaScript Getters and Setters, which provide a way to define special methods for getting and setting the values of an object's properties. This will allow us to add more control over how these properties are accessed and modified. Stay tuned!