โ Back to OOP Concepts
๐
Pillars
Polymorphism
Allows objects of different types to be treated through a common interface, with each type providing its own behavior for the same call.
The Problem
Without polymorphism, code must use type-checks and branching (if/else or switch on type) to handle different object types โ logic that grows and becomes error-prone every time a new type is added.
How It Works
- โบThe same method call produces different behavior depending on the runtime type of the object
- โบAchieved via method overriding (subtype polymorphism) or interfaces/protocols
- โบEliminates type-checking conditionals โ the right implementation is dispatched automatically
- โบEnables writing generic code that works with any conforming type
When to Use
โProcessing heterogeneous collections uniformly (e.g., an array of Shape)
โPlugin or strategy systems where behavior varies by type
โReplacing switch-on-type logic with dynamic dispatch
Real-World Examples
๐
iOS
draw() called on any UIView subclass renders that subclass's own appearance
๐ค
Android
onClick() behaves differently depending on the View subclass's listener
๐
Web
toString() overridden per class to produce custom string representations
Code Examples
Swift
protocol Shape {
func area() -> Double
}
struct Circle: Shape {
let radius: Double
func area() -> Double { .pi * radius * radius }
}
struct Rectangle: Shape {
let width: Double
let height: Double
func area() -> Double { width * height }
}
let shapes: [Shape] = [Circle(radius: 2), Rectangle(width: 3, height: 4)]
for shape in shapes {
print("Area: \(shape.area())")
}