DEV Community

Saras Growth Space
Saras Growth Space

Posted on

LLD Object-Oriented Design: Polymorphism (Design Without if-else)

After understanding inheritance, the next step is learning how systems can support multiple behaviors without constantly changing existing code.

This is where polymorphism becomes important.


What is Polymorphism?

Polymorphism means:

The same operation can behave differently depending on the object handling it.

In simple terms:

  • one common contract
  • multiple implementations
  • behavior selected at runtime

Why Polymorphism Exists

In real systems:

  • similar operations exist across different entities
  • behavior changes based on type or implementation
  • systems need extensibility without modification

Without polymorphism, systems usually rely on:

  • large if-else chains
  • switch-case logic
  • type checking everywhere

As systems grow, this becomes difficult to maintain.


Bad Design: Behavior Controlled Using if-else

class PaymentService:
    def pay(self, payment_type):
        if payment_type == "card":
            print("Card payment")
        elif payment_type == "upi":
            print("UPI payment")
Enter fullscreen mode Exit fullscreen mode

Problems with This Approach

1. Every new type requires modification

Adding WalletPayment means editing existing code.


2. Logic keeps growing

The service becomes bloated over time.


3. Violates Open-Closed Principle

The class is not closed for modification.


4. Behavior is centralized incorrectly

Service decides behavior instead of objects themselves.


Better Design: Using Polymorphism

class Payment:
    def pay(self):
        pass

class CardPayment(Payment):
    def pay(self):
        print("Card payment")

class UpiPayment(Payment):
    def pay(self):
        print("UPI payment")
Enter fullscreen mode Exit fullscreen mode

Usage

def process(payment: Payment):
    payment.pay()
Enter fullscreen mode Exit fullscreen mode

Now the caller does not care:

  • whether it is card payment
  • UPI payment
  • wallet payment

The object itself decides behavior.


What Actually Changed?

Instead of:

  • service controlling behavior using conditions

Now:

  • behavior is delegated to the object

This is the essence of polymorphism.


Key Idea: Same Message, Different Behavior

The same method call:

pay()
Enter fullscreen mode Exit fullscreen mode

can produce different behavior depending on object type:

  • CardPayment → card processing
  • UpiPayment → UPI processing
  • WalletPayment → wallet processing

Runtime Polymorphism

This behavior selection happens during runtime.

The system works with a common abstraction:

  • Payment

But actual execution depends on:

  • underlying implementation object

Important Clarification

Polymorphism is not limited to inheritance alone.

It can also be achieved through:

  • interfaces
  • abstract classes
  • shared contracts

The core idea is:

multiple implementations behind a common abstraction


Real System Example

Notification System

class Notification:
    def send(self):
        pass

class EmailNotification(Notification):
    def send(self):
        print("Email sent")

class SmsNotification(Notification):
    def send(self):
        print("SMS sent")
Enter fullscreen mode Exit fullscreen mode

Generic Usage

def notify(notification: Notification):
    notification.send()
Enter fullscreen mode Exit fullscreen mode

The calling code remains unchanged even when new notification types are added.


Why Polymorphism is Powerful

1. Extensibility

New behavior can be added without modifying existing logic.


2. Cleaner Systems

Removes large conditional chains.


3. Better Separation of Concerns

Each class owns its own behavior.


4. Improved Maintainability

Changes remain isolated to specific implementations.


Polymorphism vs if-else

if-else approach Polymorphism approach
centralized conditions distributed behavior
difficult to extend easy to extend
service controls behavior objects control behavior
violates OCP follows OCP

Common Mistake

Beginners sometimes:

  • use polymorphism but still keep if-else checks
  • create unnecessary type validations
  • tightly couple services to implementations

This defeats the purpose of polymorphism.


Design Principle

Behavior should live inside the object responsible for it, not inside a centralized conditional block.


When to Use Polymorphism

Use polymorphism when:

  • multiple implementations exist for same behavior
  • behavior varies by type
  • extensibility is important
  • new variations are expected in future

One-Line Takeaway

Polymorphism allows systems to support multiple behaviors through a common abstraction without modifying existing business logic.

Top comments (0)