Polymorphism in JavaScript
- What Is Polymorphism in JavaScript
- Why Polymorphism Is Used in JavaScript
- How Polymorphism Works in JavaScript
This tutorial revolves around the polymorphism in JavaScript.
In this lesson, we’ll learn what polymorphism is. Why is it used? How does it work, and how can we implement it in JavaScript?
What Is Polymorphism in JavaScript
Polymorphism is one of the core concepts of Object-Oriented Programming (OOP). It is good to understand the literal meaning of polymorphism before going into the details.
The word “Poly” means “many” or “multiple”, and “morph” means “form”. So, “polymorphism” means “many forms” or “multiple forms”.
Inheritance allows us to inherit the properties (attributes and methods) from the parent class into the child class. Polymorphism gets the advantage of those methods by overriding to perform various tasks.
It is further categorized into two categories:
- Static Polymorphism
- Dynamic Polymorphism
The static polymorphism occurs at compile-time, also called compile-time polymorphism. It is the same as method overloading.
As JavaScript is not compiled language, it does not natively support static polymorphism. But we can mimic it by using alternatives.
On the other hand, dynamic polymorphism happens at run time (during the program’s execution), also known as runtime polymorphism. JavaScript is interpreted language, making the method overriding possible to accomplish the dynamic polymorphism.
We’ll see both of these examples in the third section titled “working of polymorphism in JavaScript”.
Why Polymorphism Is Used in JavaScript
The polymorphism is used due to the following advantages.
- We can reuse the code that is already written and tested.
- It is easy to debug the code due to using polymorphism.
- Save time and increase the quality of the work.
How Polymorphism Works in JavaScript
This section will learn how static and dynamic polymorphism works in JavaScript.
How Static Polymorphism Works in JavaScript
Static polymorphism is the same as function overloading (we can have multiple methods with the exact name but different parameters), but this is not supported in JavaScript because JavaScript overwrites the old method with the latest one due to having the same name.
But there is a way to mimic static polymorphism. See the example code given below.
class calculator {
constructor() {}
sum(num1, num2, num3) {
if (num3 != undefined) {
console.log('Sum is called with three parameters');
return num1 + num2 + num3;
} else {
console.log('Sum is called with two parameters');
return num1 + num2;
}
}
}
const c = new calculator();
console.log(c.sum(2, 3));
console.log(c.sum(2, 3, 4));
Output:
"Sum is called with two parameters"
5
"Sum is called with three parameters"
9
We simulate static polymorphism using if-else
conditions in the code given above. We call the sum()
method twice. We pass two parameters on the first call and three on the second call.
The class calculator
is checked if the third parameter is undefined
or not. If yes, the sum()
gets executed for two parameters; otherwise, for three parameters.
Suppose we call the sum()
method for four parameters. Now, the code looks as follows.
class calculator {
constructor() {}
sum(num1, num2, num3, num4) {
if (num4 != undefined) {
console.log('Sum is called with four parameters');
return num1 + num2 + num3 + num4;
} else if (num3 != undefined) {
console.log('Sum is called with three parameters');
return num1 + num2 + num3;
} else {
console.log('Sum is called with two parameters');
return num1 + num2;
}
}
}
const c = new calculator();
console.log(c.sum(2, 3));
console.log(c.sum(2, 3, 4));
console.log(c.sum(2, 3, 4, 5));
Output:
"Sum is called with two parameters"
5
"Sum is called with three parameters"
9
"Sum is called with four parameters"
14
How Dynamic Polymorphism Works in JavaScript
Dynamic polymorphism allows us to perform a single action in multiple ways. For example, we have a function calculateArea()
, we can override that in child classes to calculate the area of the circle and the rectangle.
Inheritance is the prerequisite for dynamic polymorphism. Let’s understand with the following example.
Shape
Class:
class Shape {
calculateArea() {
console.log('shape.calculateArea is called.');
return 0;
}
}
Rectangle
Class:
class Rectangle extends Shape {
constructor(length, width) {
super();
this.length = length;
this.width = width;
}
calculateArea() {
console.log('rectangle.calculateArea is called.');
return this.length * this.width;
}
}
Circle
Class:
class Circle extends Shape {
constructor(radius) {
super();
this.radius = radius;
}
calculateArea() {
console.log('circle.calculateArea is called.');
return Math.PI * this.radius ** 2;
}
}
Main Code:
s = new Rectangle(3, 4);
console.log(s.calculateArea());
s = new Circle(2);
console.log(s.calculateArea());
Output:
"rectangle.calculateArea is called."
12
"circle.calculateArea is called."
12.566370614359172
Notice that we have the same calculateArea()
method in the parent class (which is Shape
) and child classes (Rectangle
and Circle
), but they are working differently. It is because of holding a reference of different objects.
The s
holds the reference of Rectangle
class in this code s = new Rectangle(3,4);
but it holds Circle
class’ reference in code s= new Circle(2);
.
How do we know which reference is held by the variable s
? It is decided on the run time because the objects are created on runtime; that is why it is called dynamic polymorphism.
Another question is how to find out that the method calculateArea()
is called from which class because it exists in parent and all child classes.
Again, it depends on the objects that are created on runtime. Let’s say s
holds the object of the Circle
class, and Circle
has overridden the calculateArea()
method.
The calculateArea()
from the Circle
class will be called in this case.
Just assume that the Circle
does not override the calculateArea()
method; in this case, the calculateArea()
method will be called from the parent of Circle
, which is Shape
.
To practice, remove calculateArea()
from the Circle
class and run the code; you will see the following output.
"rectangle.calculateArea is called."
12
"shape.calculateArea is called."
0
Did you notice that calculateArea()
is called from the Shape
class? It is because the Circle
class has not overridden it.