100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

What is Double Dispatch in OOP?

Learn double dispatch in OOP — why single dispatch falls short and how chained virtual calls resolve behavior on two types.

hardQ192 of 226 in Object Oriented Programming Est. time: 6 minsLast updated:
Open Code Lab

Expected Interview Answer

Double dispatch is a technique where the method that executes is selected based on the runtime types of TWO objects involved in a call, not just one, achieved by combining virtual method calls with an overloaded method on the second object.

Most object-oriented languages, including Java and C++, only support single dispatch: a virtual call is resolved using the runtime type of the receiver object, while the argument types are resolved statically at compile time using the declared (static) type. Double dispatch simulates resolving on both types by having the first virtual call turn around and invoke a second virtual call on the argument, passing “this” (with its now-known concrete type) back in. This is the mechanism the Visitor design pattern relies on to add new operations over a class hierarchy without touching the hierarchy itself. Without double dispatch, code that needs to branch on the concrete types of two interacting objects (like collision handling between different shape types) collapses into brittle instanceof chains.

  • Resolves behavior correctly using both objects’ runtime types
  • Avoids long instanceof/switch chains for type-pair logic
  • Foundation for the Visitor pattern
  • Keeps type-pair logic extensible without modifying existing classes

AI Mentor Explanation

When a fielder catches a ball, what actually happens depends on both the fielder’s specific role (wicketkeeper vs outfielder) and the type of delivery that produced the catch (spin vs pace edge). A single lookup on just the fielder’s type is not enough; the umpire’s ruling engine effectively asks the fielder to react, and that reaction then asks the ball type what specific handling applies. That two-step “ask, then ask again” resolution based on both actors’ real types is exactly what double dispatch achieves in code.

Step-by-Step Explanation

  1. Step 1

    Recognize the limitation of single dispatch

    A virtual call resolves the receiver by runtime type but resolves overloaded arguments by their static (declared) type only.

  2. Step 2

    First virtual call on the receiver

    Call an overridden method on object A; this resolves using A’s concrete runtime type.

  3. Step 3

    Call back into the argument

    Inside that method, call an overloaded method on object B, passing “this” (A) as the argument.

  4. Step 4

    Second virtual call resolves on B

    B’s overridden method now runs using B’s concrete runtime type, so the pair (A, B) both contributed to selecting the final method.

What Interviewer Expects

  • Correct explanation of why single dispatch is insufficient for type-pair decisions
  • A concrete mechanism: two chained virtual/overridden calls, not just “it uses two types”
  • Connection to the Visitor pattern as the canonical use case
  • A worked or code example, not just a definition

Common Mistakes

  • Confusing double dispatch with simple method overloading
  • Claiming Java or C++ natively resolve on both runtime types without the visitor trick
  • Describing it only abstractly without the two-call chain mechanism
  • Mixing it up with multiple dispatch (resolving on more than two types, common in other languages)

Best Answer (HR Friendly)

Double dispatch is a way to pick the right method to run based on the actual types of two objects working together, not just one. Since most languages like Java only let you resolve behavior using one object’s real type at a time, double dispatch chains two calls together: the first object calls back into the second, so the second call resolves using the second object’s real type too. It is the technique that makes the Visitor design pattern work.

Code Example

Double dispatch via visitor-style method chaining
interface Shape {
    void accept(ShapeVisitor visitor);
}

class Circle implements Shape {
    public void accept(ShapeVisitor visitor) { visitor.visit(this); }
}

class Square implements Shape {
    public void accept(ShapeVisitor visitor) { visitor.visit(this); }
}

interface ShapeVisitor {
    void visit(Circle c);
    void visit(Square s);
}

class AreaPrinter implements ShapeVisitor {
    public void visit(Circle c) { System.out.println("Circle area logic"); }
    public void visit(Square s) { System.out.println("Square area logic"); }
}

Shape shape = new Circle();
shape.accept(new AreaPrinter());
// First dispatch: accept() resolves on shape’s real type (Circle)
// Second dispatch: visit(this) resolves on the overload matching Circle

Follow-up Questions

  • Why can’t Java resolve overloaded methods using an argument’s runtime type directly?
  • How does the Visitor pattern rely on double dispatch?
  • What is the difference between double dispatch and multiple dispatch?
  • What problem arises if you add a new Shape type to a Visitor-based hierarchy?

MCQ Practice

1. Double dispatch resolves a method call based on?

Double dispatch chains two virtual calls so the final method is selected using the runtime types of both objects involved.

2. Which design pattern is built directly on double dispatch?

The Visitor pattern uses accept()/visit() chained calls to achieve double dispatch across an object hierarchy.

3. In Java, a normal overloaded method call is resolved using?

Java resolves overload selection at compile time based on the declared static type of the argument expression.

Flash Cards

Double dispatch in one line?Selecting a method using the runtime types of two objects via two chained virtual calls.

Why is it needed in Java?Because overloaded methods resolve on static argument type, not runtime type.

Which pattern uses it?The Visitor pattern, via accept()/visit().

What is the first call in the chain?A virtual call on the receiver object that resolves using its concrete runtime type.

1 / 4

Continue Learning