Programming languages · intermediate
Polymorphism and dispatch
Polymorphism lets one expression or interface work with values of multiple types. Dispatch is the mechanism that selects an applicable implementation, which can occur dynamically from a runtime receiver type, statically through overloading, or through other language-defined forms.
Why it matters
Polymorphism separates clients from concrete implementations, while dispatch rules determine which code actually runs. Precise distinctions prevent surprises involving overrides, overloads, generics, and substitutability.
Mental model
How to reason about polymorphism and dispatch
A call site states an operation through a contract. The language uses static types, runtime types, type arguments, or argument patterns to choose code according to a documented dispatch rule.
Analogy
Polymorphism is a common request form accepted by several specialist desks; dispatch is the routing rule that decides which desk handles this particular request.
Examples
See the boundary, not just the happy path
Worked example · Runtime receiver dispatch
Shape shape = new Circle(2); shape.area();In Java, the overridden instance method selected for area is based on the runtime class Circle, while the static type Shape determines which members are valid at the call site.
Worked example · Parametric polymorphism
T first<T>(List<T> items) => items.first;The Dart function works uniformly for many element types while preserving the relationship between input and output types. This is polymorphism without choosing among subclass method bodies.
Useful contrast · Overload selection can be static
print(int value) versus print(String value)In languages with overloading, the compiler can select a signature using static argument types. That differs from dynamic dispatch of an overridden instance method.
Common mistakes
Misconceptions to remove early
Reducing all polymorphism to inheritance
Interfaces, structural typing, generics, protocols, traits, and ad-hoc overloads provide other forms. Inheritance is one possible mechanism, not the definition.
Ignoring behavioral substitutability
A subtype that satisfies method signatures but violates promised behavior can break callers. Useful polymorphism requires implementations to preserve the interface's semantic contract.
Quick check
Can you predict the result?
1. In a typical overridden Java instance call, what selects the method body?
- • The runtime class of the receiver, subject to Java's dispatch rules.
- • The variable name's spelling.
- • The order of files in the source directory.
2. Why is a generic identity-like function polymorphic without subclass dispatch?
Keep building