What is Replace Conditional with Polymorphism?
Learn the Replace Conditional with Polymorphism refactoring — trading type-code branches for overriding subclasses — with a Java example.
Expected Interview Answer
Replace Conditional with Polymorphism is the refactoring that removes a branching statement — usually a switch or if/else chain keyed on an object’s type — by moving each branch’s behavior into an overriding method on a corresponding subclass, letting dynamic dispatch pick the correct behavior instead of explicit type checks.
The trigger is a conditional that behaves differently depending on a type code or the runtime type of an object, and that same conditional shape tends to reappear at multiple call sites throughout the codebase. The fix is to define a class hierarchy where each concrete case becomes its own subclass overriding a common method, so calling code just invokes the method polymorphically and the correct implementation runs automatically. Adding a new case then means adding a new subclass rather than editing every place the conditional was duplicated, which satisfies the open-closed principle. It is not free — it introduces more classes and can be overkill for a conditional used in exactly one place, so it is judged by whether the conditional recurs and how likely new cases are.
- Eliminates duplicated type-checking conditionals scattered across the codebase
- New cases are added via new classes, not by editing existing logic (open-closed principle)
- Moves behavior next to the data it operates on
- Makes intent clearer by naming each case as its own type
AI Mentor Explanation
Instead of a scorer running an if/else on player role every time they log an action — 'if batter, do this; if bowler, do that; if fielder, do this other thing' — each role is given its own logAction() method, and the scorer just calls player.logAction() without checking who it is. Adding a new role, like an all-rounder, means writing one new class, not editing the scorer’s branching logic everywhere it appears. That is Replace Conditional with Polymorphism: type-checking branches are replaced by each type knowing its own behavior.
Step-by-Step Explanation
Step 1
Find the recurring conditional
Locate the type-code or instanceof-style branching that repeats across the codebase.
Step 2
Define a common method
Declare an abstract method (or interface method) representing the varying behavior.
Step 3
Create a subclass per case
For each branch, create a subclass that overrides the method with that branch's logic.
Step 4
Replace call sites
Replace each conditional call site with a plain polymorphic call, then delete the now-dead conditional.
What Interviewer Expects
- Recognition that the trigger is a type-code conditional repeated across the codebase
- Correct mechanics: one subclass per branch, overriding a common method
- Connection to the open-closed principle (new cases via new classes, not edits)
- Awareness that this refactoring is not always worth it for a single, non-repeated conditional
Common Mistakes
- Applying it to a one-off conditional that never repeats, adding needless class overhead
- Forgetting to remove the now-redundant conditional/type-check code after refactoring
- Confusing this with Extract Method, which does not involve subclassing
- Not considering that new cases still require compiling and deploying a new subclass
Best Answer (HR Friendly)
“Replace Conditional with Polymorphism means taking an if/else or switch statement that behaves differently depending on an object’s type, and instead giving each type its own subclass with its own version of the method. Then the calling code just calls the method and the right behavior happens automatically, so adding a new case means adding a new class instead of editing that conditional everywhere it appears.”
Code Example
// Before: type-code conditional repeated wherever pay is calculated
double calculatePay(Employee e) {
switch (e.getType()) {
case ENGINEER: return e.getBaseSalary() * 1.1;
case MANAGER: return e.getBaseSalary() * 1.25;
case INTERN: return e.getBaseSalary() * 0.5;
default: throw new IllegalArgumentException();
}
}
// After: each type overrides its own calculation
abstract class Employee {
protected double baseSalary;
abstract double calculatePay();
}
class Engineer extends Employee {
@Override double calculatePay() { return baseSalary * 1.1; }
}
class Manager extends Employee {
@Override double calculatePay() { return baseSalary * 1.25; }
}
class Intern extends Employee {
@Override double calculatePay() { return baseSalary * 0.5; }
}
// Call site: no conditional needed at all
double pay = employee.calculatePay();Follow-up Questions
- When would this refactoring not be worth applying?
- How does this refactoring relate to the open-closed principle?
- What is the difference between this and the State or Strategy design pattern?
- How do you handle a default/fallback case once the conditional is removed?
MCQ Practice
1. The main trigger for Replace Conditional with Polymorphism is?
This refactoring targets recurring type-based conditionals scattered across the codebase.
2. After this refactoring, adding a new case requires?
New cases are added as new subclasses, leaving existing code untouched — the open-closed principle.
3. Replace Conditional with Polymorphism is best avoided when?
For a single, stable, non-repeated conditional, introducing a class hierarchy can be unnecessary overhead.
Flash Cards
Replace Conditional with Polymorphism in one line? — Move each conditional branch's logic into an overriding method on its own subclass.
Trigger to look for? — A type-code or instanceof conditional whose shape repeats across the codebase.
Principle it satisfies? — Open-closed principle — new cases via new subclasses, not edited conditionals.
When to avoid it? — When the conditional appears once and new cases are unlikely.