Clean Code with Polymorphism in TypeScript

Introduction

Welcome to the next lesson of the Clean Code with Multiple Classes course! This lesson is all about putting polymorphism into practice, building on the foundations laid in previous lessons, such as class collaboration, interfaces, abstract classes, and dependency management. Polymorphism is a cornerstone concept in object-oriented programming (OOP) that allows us to write more dynamic and flexible code. Today, we will explore its practical applications and how it can enhance code quality. Let's dive in!

Benefits of Using Polymorphism

Polymorphism empowers developers to write flexible and scalable code. It allows objects to be treated as instances of their parent class, paving the way for code that is both maintainable and extendable. Consider a scenario where you have multiple classes representing different types of payments: CreditCardPayment, PayPalPayment, and BankTransferPayment. By using polymorphism, you can treat these different payment types in a unified way.

Here's a basic example illustrating this concept in TypeScript:

abstract class Payment {
    abstract pay(): void;
}

class CreditCardPayment extends Payment {
    pay(): void {
        console.log("Processing credit card payment.");
    }
}

class PayPalPayment extends Payment {
    pay(): void {
        console.log("Processing PayPal payment.");
    }
}

By using a common interface or abstract class (Payment, in this case), different payment methods can be handled through a single reference type:

function processPayment(payment: Payment) {
    payment.pay();
}

// You can pass any derived class object to processPayment.
let payment: Payment = new CreditCardPayment();
processPayment(payment);

This example demonstrates the core benefit of polymorphism: the ability to write code that can work with objects of different classes in a unified manner. This flexibility reduces code duplication and makes it easier to add new payment types by implementing the Payment class without altering existing logic.

Key Problems Addressed by Polymorphism

One of the recurring issues in software development is rigid code that's difficult to modify or extend. Polymorphism offers a way out by enabling more abstract and adaptive design patterns. Let's revisit a problem you might have seen before: a program littered with conditional statements to handle different behaviors based on object types.

Consider the following code without polymorphism:

function processPaymentDetails(paymentMethod: any): void {
    if (paymentMethod instanceof CreditCardPayment) {
        // Process credit card payment
    } else if (paymentMethod instanceof PayPalPayment) {
        // Process PayPal payment
    }
    // More conditions...
}

Polymorphism helps eliminate such long conditional logic. Here's how the same functionality could be achieved using polymorphism:

function processPayment(payment: Payment): void {
    payment.pay();
}

By designing your classes to use polymorphism, you avoid cumbersome conditional structures that can be error-prone and hard to maintain.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal