Skip to main content

What is Polymorphism 🤔

Polymorphism is a fundamental concept in object-oriented programming (OOP) that allows objects of different classes to be treated as objects of a common superclass.

Polymorphism In TypeScript

It enables a single interface or method to work with different types of data, providing flexibility and reusability in the code. The three main types of polymorphism in OOP are:

  1. Subtype polymorphism (also known as inheritance or implementation polymorphism)
  2. Parametric polymorphism (also known as generics)
  3. Ad hoc polymorphism (also known as function overloading or operator overloading)

Subtype Polymorphism

In the context of OOP, subtype polymorphism is the most commonly used form. It is achieved through inheritance, where a subclass inherits properties and methods from a superclass, and can also override or extend the inherited properties and methods.

Here's an example using TypeScript to demonstrate polymorphism through inheritance:

// Define a base class 'Shape' with a common method 'area'
abstract class Shape {
abstract area(): number;
}

// Define a 'Rectangle' class that extends the base class 'Shape'
class Rectangle extends Shape {
constructor(private width: number, private height: number) {
super();
}

// Override the 'area' method for 'Rectangle'
area(): number {
return this.width * this.height;
}
}

// Define a 'Circle' class that extends the base class 'Shape'
class Circle extends Shape {
constructor(private radius: number) {
super();
}

// Override the 'area' method for 'Circle'
area(): number {
return Math.PI * this.radius * this.radius;
}
}

// Create instances of 'Rectangle' and 'Circle'
const rect: Shape = new Rectangle(5, 4);
const circle: Shape = new Circle(3);

// Define a function to use the common interface for calculating the total area of an array of shapes
function getTotalArea(shapes: Shape[]): number {
return shapes.reduce((totalArea, shape) => totalArea + shape.area(), 0);
}

// Use the getTotalArea function with an array of different shape objects
const totalArea = getTotalArea([rect, circle]);
console.log(`Total area of shapes: ${totalArea}`);

In this example, we define an abstract class Shape with an abstract method area. The Rectangle and Circle classes extend Shape and override the area method with their respective implementations. We can then treat instances of Rectangle and Circle as instances of Shape and use the getTotalArea function to calculate the total area of an array of shapes. This demonstrates polymorphism in action, as different shape objects can be treated as instances of the common superclass Shape.

TypeScript Course Instructor Image
TypeScript Course Instructor Image

Time To Transition From JavaScript To TypeScript

Level Up Your TypeScript And Object Oriented Programming Skills. The only complete TypeScript course on the marketplace you building TypeScript apps like a PRO.

SEE COURSE DETAILS

Parametric polymorphism

Parametric polymorphism, also known as generics, is a form of polymorphism in which a function, class, or interface can work with multiple types without depending on any specific concrete type. It allows the same code to work with different data types, providing flexibility, reusability, and type safety.

Generics in TypeScript are a way to implement parametric polymorphism. By using type parameters, you can create generic functions, classes, or interfaces that can work with multiple types while maintaining type information.

Here's an example using TypeScript to demonstrate parametric polymorphism through generics:

// Define a generic function 'identity' that returns the input value
function identity<T>(value: T): T {
return value;
}

// Use the 'identity' function with different data types
const numIdentity: number = identity<number>(42);
const strIdentity: string = identity<string>("Hello, TypeScript!");

console.log(`Number identity: ${numIdentity}`);
console.log(`String identity: ${strIdentity}`);

// Define a generic class 'Pair' that can store two values of the same type
class Pair<T> {
constructor(public first: T, public second: T) {}

// Swap the first and second values
swap(): void {
const temp = this.first;
this.first = this.second;
this.second = temp;
}
}

// Use the 'Pair' class with different data types
const numPair: Pair<number> = new Pair(1, 2);
const strPair: Pair<string> = new Pair("Alice", "Bob");

numPair.swap();
strPair.swap();

console.log(`Number pair after swap: (${numPair.first}, ${numPair.second})`);
console.log(`String pair after swap: (${strPair.first}, ${strPair.second})`);

In this example, we define a generic function identity that accepts a type parameter T and a value of type T, and returns the value unchanged. This function can be used with different data types, such as numbers and strings.

We also define a generic class Pair that accepts a type parameter T and can store two values of the same type. The Pair class has a swap method that swaps the values of its first and second properties. The Pair class can be used with different data types, such as numbers and strings, while maintaining type safety.

By using generics, we create reusable and flexible code that can work with different types without depending on any specific concrete type. This is an example of parametric polymorphism in TypeScript.

What Can You Do Next 🙏😊

If you liked the article, consider subscribing to Cloudaffle, my YouTube Channel, where I keep posting in-depth tutorials and all edutainment stuff for software developers.

YouTube @cloudaffle