10.1 Basics of Polymorphism
Polymorphism is one of the key concepts of object-oriented programming (OOP). Generally speaking, polymorphism allows objects of different classes to handle data using the same interface. In the context of JavaScript, this means that different objects can have methods with the same names, and these methods can be called on the objects without knowing their exact type.
Types of Polymorphism
In JavaScript, the main types of polymorphism are:
1. Ad-hoc polymorphism:
- Method polymorphism, calling methods with the same name for objects of different types
- Examples include function and operator overloading (which is not directly supported in JavaScript, but can be simulated)
2. Subtype polymorphism:
- Subtype or inclusion polymorphism, where objects of different classes inheriting from the same base class can be treated as objects of the base class
- This is the main type of polymorphism implemented through inheritance and interfaces
Advantages of Polymorphism:
- Simplifying code: polymorphism allows writing more flexible and generalized code that can work with different object types without knowing their specific types.
- Extensibility: polymorphism makes it easier to add new types and behaviors to the system without needing to change existing code.
- Maintenance: polymorphism promotes better separation of concerns and increases code readability and maintainability.
10.2 Examples of Polymorphism in JavaScript
Subtype polymorphism through inheritance
Example 1: Handling different object types with a single interface
In this example, the function playWithAnimal
takes an object of type Animal
and calls the method
makeSound
. The objects Dog
and Cat
, which inherit from Animal
,
override the method makeSound
, and when the method is called on each object, it produces different results.
class Animal {
makeSound() {
console.log('Some generic sound');
}
}
class Dog extends Animal {
makeSound() {
console.log('Woof!');
}
}
class Cat extends Animal {
makeSound() {
console.log('Meow!');
}
}
function playWithAnimal(animal) {
animal.makeSound();
}
const dog = new Dog();
const cat = new Cat();
playWithAnimal(dog); // Outputs: Woof!
playWithAnimal(cat); // Outputs: Meow!
10.3 Polymorphism through Interfaces (Duck Typing)
JavaScript does not have built-in support for interfaces like other languages such as TypeScript or Java. Instead, a concept called "Duck Typing" is used. This means an object is considered to conform to an interface if it has the required methods and properties, regardless of its specific type or inheritance.
Duck rule: if something looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.
Example 2: Using Duck Typing
In this example, the function takeOff
takes any object that has a method fly
. The objects
Bird
and Airplane
implement the method fly
, and therefore can be passed to
takeOff
.
class Bird {
fly() {
console.log('Flying...');
}
}
class Airplane {
fly() {
console.log('Jet engine roaring...');
}
}
function takeOff(flyingObject) {
flyingObject.fly();
}
const bird = new Bird();
const airplane = new Airplane();
takeOff(bird); // Outputs: Flying...
takeOff(airplane); // Outputs: Jet engine roaring...
10.4 Polymorphism through Functions
In JavaScript, functions are first-class objects, and they can be passed around and used to implement polymorphic behavior.
Example 3: Polymorphism through Functions
In this example, the function greet
takes another function as an argument and calls it. This allows
using different functions to perform different actions.
function greetMorning() {
console.log('Good morning!');
}
function greetEvening() {
console.log('Good evening!');
}
function greet(greetingFunction) {
greetingFunction();
}
greet(greetMorning); // Outputs: Good morning!
greet(greetEvening); // Outputs: Good evening!
10.5 Polymorphism through Method Overloading (Simulation)
JavaScript does not support direct method overloading like some other programming languages. However, method overloading can be simulated using function arguments and type checking.
Example 4: Simulating Method Overloading
In this example, the method add
takes two arguments and performs different actions based on their types.
If the arguments are numbers, the method adds them. If the arguments are arrays, the method concatenates them.
class Calculator {
add(a, b) {
if (typeof a === 'number' && typeof b === 'number') {
return a + b;
} else if (Array.isArray(a) && Array.isArray(b)) {
return a.concat(b);
} else {
throw new Error('Invalid arguments');
}
}
}
const calc = new Calculator();
console.log(calc.add(1, 2)); // Outputs: 3
console.log(calc.add([1, 2], [3, 4])); // Outputs: [1, 2, 3, 4]
GO TO FULL VERSION