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:
- Subtype polymorphism (also known as inheritance or implementation polymorphism)
- Parametric polymorphism (also known as generics)
- 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
.
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 DETAILSParametric 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.