Language: EN

javascript-herencia-y-polimorfismo

Inheritance and Polymorphism in JavaScript

The inheritance is a feature that allows creating new classes based on existing classes.

With inheritance, a class can have the properties and methods of another, while adding or overriding with its own methods.

This relationship between classes is known as parent-child or superclass-subclass relationship.

In JavaScript, inheritance is primarily implemented through classes, which were introduced in ECMAScript 6 (ES6).

Before ES6, JavaScript used constructor functions and the prototype object to implement inheritance. With the introduction of class syntax, inheritance became simpler and clearer.

Basic Syntax of Inheritance

In JavaScript, to create a subclass that inherits from the base class, we use the keyword extends.

First, we need to define a base class, and then we would create the derived class. For example, like this:

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

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

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

  speak() {
    console.log(`${this.name} says Woof!`);
  }
}

const myDog = new Dog('Rex', 'Labrador');
myDog.speak(); // "Rex says Woof!"

In this example:

  • Animal is the base class that has a constructor that assigns a value to name and a method called speak().
  • Dog is a subclass that inherits from Animal. It uses the super() method to call the constructor of the base class and assign the value to name.
  • Additionally, it overrides the speak() method to customize the specific behavior of dogs.

Super Keyword

The super() keyword allows us to get a reference to the base class from the derived class. For example, it is used to:

  1. Call the superclass constructor: When we need to initialize inherited properties from the base class.
  2. Access superclass methods: To use methods from the superclass within the subclass.
class Dog extends Animal {
  constructor(name, breed) {
    super(name); // Calls the constructor of the parent class
    this.breed = breed; // Additional property
  }
}

In the previous example,

  • super(name) calls the constructor of Animal and passes the argument name so that the name property is initialized.

Inherited Properties and Methods

When a subclass inherits from a superclass, it inherits its properties and methods. This means we can access the properties and methods of the superclass as if they were defined directly in the subclass.

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

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

class Cat extends Animal {
  // No need to redefine 'name', as it is inherited from Animal
}

const myCat = new Cat('Whiskers');
myCat.speak(); // "Whiskers makes a sound"

Here, Cat inherits the speak() method from Animal and can use it without having to redefine it.

Overriding Methods in the Subclass

One feature of inheritance is that we can override the methods of the base class in the subclass. This allows us to customize the behavior.

This is useful when we want subclasses to have specific behaviors while retaining the foundation of the original class.

class Cat extends Animal {
  speak() {
    console.log(`${this.name} says Meow!`);
  }
}

const myCat = new Cat('Rufus the cat');
myCat.speak(); // "Rufus the cat says Meow!"

In this case, Cat redefines the speak() method so that it makes a different sound than Animal.

Static Properties and Inheritance

Subclasses also inherit static properties. The base class and the derived class share static variables and methods (the derived class does not have its own versions)

class Animal {
  static species = 'Animal'; // Static property

  //... more things
}

class Dog extends Animal {}

console.log(Dog.species); // "Animal"

Dog.species = "Doggo";
console.log(Animal.species); // "Doggo"

Here,

  • The static property species is inherited by the subclass Dog.
  • If we access Dog.species, we get Animal.
  • When we modify Dog.species, we also modify Animal.species.
  • That is, the property species is the same for both classes.

What is Polymorphism?

In other words, polymorphism allows objects of different classes to have different behaviors for the same method.

In JavaScript, polymorphism can be achieved using inheritance and method overriding. Let’s see it with an example:

let animal = new Animal('Animal');
let cat = new Cat('Cat');
let dog = new Dog('Dog');

animal.makeSound(); // Making sound...
cat.makeSound(); // Meow!
dog.makeSound(); // Woof!
class Animal {
  constructor(name) {
    this.name = name;
  }

  makeSound() {
    console.log('Making sound...');
  }
}
class Cat extends Animal {
  constructor(name) {
    super(name);
  }

  makeSound() {
    console.log('Meow!');
  }
}
class Dog extends Animal {
  constructor(name) {
    super(name);
  }

  makeSound() {
    console.log('Woof!');
  }
}

In this example,

  • We have a class Animal with a method makeSound().
  • The Cat class and the Dog class inherit from the Animal class and override the makeSound() method with their own implementations.
  • When the makeSound() method is called on each object, the behavior is different according to the class of the object.