OOP Dispatch: Dynamic Binding, Single & Double Dispatch
This post is a term explanation for dispatch in object-oriented programming – including exam questions and tags.
In a Nutshell
Dispatch refers to the selection of the actual method to be executed for a call. Depending on the language and construct, binding occurs statically at compile time or dynamically at runtime, forming the basis for polymorphism.
Compact Technical Description
Dispatch refers to the resolution of a method call to a concrete implementation. In static dispatch (overloading), the compiler decides based on static types. In dynamic dispatch (overriding), the runtime environment decides based on the actual object type, often via a vtable.
Dispatch variants:
- Single Dispatch: Selection based on the receiver object
- Double Dispatch: Selection based on two runtime types (Visitor Pattern)
- Multiple Dispatch: Selection based on multiple runtime arguments
Dynamic binding enables polymorphism and the Open Closed Principle, but requires correct contracts according to the Liskov Substitution Principle. Static dispatch offers predictability and performance, dynamic dispatch offers flexibility and extensibility.
Exam-Relevant Key Points
- Static Dispatch: Overloading, compile-time decision
- Dynamic Dispatch: Overriding, runtime decision
- vtable: Dispatch table for polymorphic calls
- Single Dispatch: Only receiver type decides
- Double Dispatch: Receiver and parameter decide
- Visitor Pattern: Implements double dispatch
- Performance: Static dispatch faster than dynamic
- IHK-relevant: Distinction between overloading vs overriding
Core Components
- Virtual Method Table (vtable): Dispatch table for polymorphic methods
- Single Dispatch: Standard OOP dispatch mechanism
- Double Dispatch: Visitor pattern for complex type relationships
- Method Overriding: Dynamic binding in inheritance
- Method Overloading: Static binding at compile time
- Runtime Type Information (RTTI): Type information at runtime
- Dynamic Binding: Resolution at runtime
- Static Binding: Resolution at compile time
Practical Examples
Single Dispatch (Standard OOP)
// Single Dispatch - only the receiver type decides
abstract class Tier {
abstract void machGeraeusch();
}
class Hund extends Tier {
@Override
void machGeraeusch() {
System.out.println("Wuff!");
}
}
class Katze extends Tier {
@Override
void machGeraeusch() {
System.out.println("Miau!");
}
}
// Dynamic binding at runtime
Tier tier = new Hund(); // Static type: Tier, Dynamic type: Hund
tier.machGeraeusch(); // Output: "Wuff!" (Single Dispatch)
Double Dispatch with Visitor Pattern
// Double Dispatch - receiver and parameter decide
interface Tier {
void akzeptiere(Besucher besucher);
}
class Hund implements Tier {
@Override
public void akzeptiere(Besucher besucher) {
besucher.besuche(this); // Double Dispatch
}
}
class Katze implements Tier {
@Override
public void akzeptiere(Besucher besucher) {
besucher.besuche(this); // Double Dispatch
}
}
interface Besucher {
void besuche(Hund hund);
void besuche(Katze katze);
}
class Tierarzt implements Besucher {
@Override
public void besuche(Hund hund) {
System.out.println("Untersuche Hund: Impfung geben");
}
@Override
public void besuche(Katze katze) {
System.out.println("Untersuche Katze: Krallen schneiden");
}
}
// Usage
Tier[] tiere = {new Hund(), new Katze()};
Besucher tierarzt = new Tierarzt();
for (Tier tier : tiere) {
tier.akzeptiere(tierarzt); // Double Dispatch
}
// Output:
// Untersuche Hund: Impfung geben
// Untersuche Katze: Krallen schneiden
Static vs Dynamic Dispatch
class Rechner {
// Static Dispatch (Overloading)
public int addiere(int a, int b) {
return a + b;
}
public double addiere(double a, double b) {
return a + b;
}
}
class PolymorpherRechner {
// Dynamic Dispatch (Overriding)
public virtual int berechne(int a, int b) {
return a + b;
}
}
class Multiplizierer extends PolymorpherRechner {
@Override
public int berechne(int a, int b) {
return a * b;
}
}
// Static Dispatch at compile time
Rechner rechner = new Rechner();
int ergebnis1 = rechner.addiere(1, 2); // Compile: addiere(int, int)
// Dynamic Dispatch at runtime
PolymorpherRechner poly = new Multiplizierer();
int ergebnis2 = poly.berechne(3, 4); // Runtime: Multiplizierer.berechne()
Advantages and Disadvantages
Advantages of Dynamic Dispatch
- Flexibility: Runtime polymorphism enables extensible systems
- Maintainability: Add new types without code changes
- Abstraction: Unified treatment of different types
- Open Closed Principle: Extensible without modification
Disadvantages
- Performance: Runtime overhead from vtable lookup
- Complexity: Harder to understand and debug
- Memory: Additional vtable structures
- Error-proneness: Runtime errors instead of compile-time errors
Dispatch Mechanisms in Different Languages
Java
// Standard: Single dispatch with vtable
// Double dispatch via Visitor Pattern
interface Shape {
double area();
void accept(Visitor visitor);
}
C++
// Direct Support: Multiple Dispatch
#include <boost/variant.hpp>
struct DoubleDispatcher {
void collide(Asteroid& a, Spaceship& s) { /* ... */ }
void collide(Spaceship& s, Asteroid& a) { /* ... */ }
};
Python
# Duck Typing: Dynamic resolution
class Animal:
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
return "Woof!"
# Dynamic binding at runtime
def animal_sound(animal):
return animal.make_sound() # Dispatch at runtime
Common Exam Questions
-
What is the difference between single and double dispatch? Single dispatch considers only the receiver type, double dispatch considers receiver and parameter types.
-
How does a vtable work? A vtable is an array of function pointers that resolves polymorphic method calls at runtime.
-
When do you use the Visitor Pattern? When operations must be separated from the data structure and double dispatch is required.
-
Why is dynamic dispatch slower than static dispatch? Because runtime vtable lookup is required instead of direct method calls at compile time.
Most Important Sources
- https://en.wikipedia.org/wiki/Dynamic_dispatch
- https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
- https://refactoring.guru/design-patterns/visitor