Conceptly
← All Concepts
🎭

Polymorphism

BehavioralThe property that the same call can behave differently by type

Polymorphism is the property that callers can interact through one interface or base type while the actual behavior depends on the concrete runtime type. The caller does not need to know the class name to keep the collaboration working.

β–ΆArchitecture Diagram

πŸ”„ Process

Dashed line animations indicate the flow direction of data or requests

Why do you need it?

If every new type requires yet another if or switch branch in the caller, the burden of change accumulates in the wrong place. Adding one behavior then means editing many call sites instead of letting the new type own its own behavior.

Why did this approach emerge?

Object-oriented design evolved by pushing behavioral variation into types so callers could stop branching on concrete cases. Virtual methods and interface-driven programming matter because they allow systems to grow by adding implementations rather than by expanding centralized conditionals.

How does it work inside?

A caller invokes a method through a shared contract. At runtime, dispatch selects the implementation that belongs to the concrete object actually supplied, which is why the same call can trigger different internal logic for different types.

Boundaries & Distinctions

Polymorphism is often associated with inheritance, but they are not identical. Good polymorphism can come from interface implementation and composition as well; inheritance is only one possible path to runtime variation.

When should you use it?

Polymorphism is especially useful for payment strategies, notification channels, file stores, and renderers where the role stays stable and only the concrete behavior changes. If the number of cases is tiny and stable, however, introducing an extra abstraction layer can cost more than a simple explicit branch.

Swap strategies -- plug different policy objects behind the same roleRemove conditionals -- push type-specific behavior into the types themselvesExtend with plugins -- add new implementations without rewriting callersSupport framework hooks -- let one flow dispatch to different concrete steps