TITLE: Another example of multiple dispatching [ This tip is here so you can recognize evil when you see it. Don't use multiple dispatching. Its klunky and does not maintain well. -adc ] PROBLEM: scofield@apollo.HP.COM (Cary Scofield) Recently, I heard someone, in the context of describing an invocation technique in object-oriented programming, use the phrase "double dispatching" (as a particular case of "multi-way dispatching"), saying that it was an idea borrowed from CLOS and that it could be done in C++. Would any of you OO/C++ geeks care to shed some light on this particular topic, please? RESPONSE: rmartin@rcmcon.com (Robert Martin), 1 Feb 94 Single dispatch is simple. The function selected depends upon the type that it is applied to. If we say shape->draw(), then the actual draw function that is called depends upon the type of the shape. If the shape is a square, the draw function for square is called. If it is a circle then the draw function for circle is called. Multi-dispatch is similar, except that the actual function called depends upon more than one type. Consider: double IntersectionArea(const Shape&, const Shape&); What function can be used to calculate the intersection area of two shapes? It depends upon the the types of the two shapes. The algorithm will be different for every different combination of shapes. Assume that there are three different derivatives of Shape: Circle, Square and Polygon. Then we would need to write: double IntersectionArea(const Square&, const Square&) double IntersectionArea(const Square&, const Circle&) double IntersectionArea(const Square&, const Polygon&) double IntersectionArea(const Circle&, const Square&) double IntersectionArea(const Circle&, const Circle&) double IntersectionArea(const Circle&, const Polygon&) double IntersectionArea(const Polygon&, const Square&) double IntersectionArea(const Polygon&, const Circle&) double IntersectionArea(const Polygon&, const Polygon&) This covers all the cases. However it does not help us with polymorphism. Shape& x = /* some derivative */; Shape& y = /* some derivative */; double area = IntersectionArea(x,y); // This has no meaning since we // don't know the true types. We can simulate double polymorphic dispatch in C++ by using a nasty trick. Unfortunately, this trick breaks the nice dependency structure of the OO code; as you'll see. class Shape { public: virtual double IntersectionArea(const Shape&) = 0; virtual double CircleIntersectionArea(const Circle&) = 0; virtual double SquareIntersectionArea(const Square&) = 0; virtual double PolygonIntersectionArea(const Polygon&) = 0; }; class Square : public Shape { public: virtual double IntersectionArea(const Shape& s) {return s.SquareIntersectionArea(*this);} virtual double CircleIntersectionArea(const Circle& c) {return IntersectonArea(*this, c);} virtual double SquareIntersectionArea(const Square& s) {return IntersectionArea(*this, s);} virtual double PolygonIntersectionArea(const Polygon& p) {return IntersectionArea(*this, p);} }; // I leave the other derivatives as an excersize. double IntersectionArea(const Shape& s1, const Shape& s2) { return s1.IntersectionArea(s2); } Now we have a polymorphic double dispatch. This works, but it has the unfortunate characteristic that the source code for the base class depends upon the source code for the derived classes. This thwarts one of the strongest benefits of OO, the ability to isolate abstractions from details. Still, if you have reason to believe that there will not be any (or many) more derivatives of Shape in the future, then this mechanism has some benefit. Clearly, if there will be many more derivatives of Shape in the future, then this method is unmanagable simply due to the geometric explosion of cominations.