Polymorphism in Practice

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, abstract base 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 in Python empowers developers to write flexible and scalable code. Rather than relying on explicit type declarations, Python embraces dynamic typing and duck typing, which allow objects to be treated according to their behavior.

Consider a scenario where you have multiple classes representing different types of payments: CreditCardPayment, PayPalPayment. By using polymorphism, you can treat these different payment types in a unified way:

from abc import ABC, abstractmethod

class Payment(ABC):
    @abstractmethod
    def pay(self):
        pass

class CreditCardPayment(Payment):
    def pay(self):
        print("Processing credit card payment.")

class PayPalPayment(Payment):
    def pay(self):
        print("Processing PayPal payment.")

By using a common method like pay, different payment methods can be handled through the concept of duck typing:

def process_payment(payment):
    payment.pay()

# You can pass any object that has a pay method to process_payment.
payment = CreditCardPayment()
process_payment(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 easy to add new payment types by simply ensuring they implement the required method 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 lengthy conditional logic to handle different behaviors based on object types.

For example, consider the following code without polymorphism:

def process_payment_details(payment_method):
    if isinstance(payment_method, CreditCardPayment):
        # Process credit card payment
    elif isinstance(payment_method, PayPalPayment):
        # Process PayPal payment
    # More conditions...

In Python, duck typing helps eliminate such cumbersome conditional structures. Here's how the same functionality could be achieved using polymorphism:

def process_payment(payment):
    payment.pay()

By designing your classes to use polymorphism, you avoid lengthy conditional checks 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