i have wrote the visitor pattern as follow but i don't understand what is single and double dispatch. AFAIK, single dispatch is invoke a method based on caller type where double dispatch is invoke a method based on caller type and argument type.
I guess double dispatch is happen in single class hierarchy but why visitor class has two class hierarchy but it still considered as double dispatch.
void floppyDisk::accept(equipmentVisitor* visitor)
{
visitor->visitFloppyDisk(this);
}
void processor::accept(equipmentVisitor* visitor)
{
visitor->visitProcessor(this);
}
void computer::accept(equipmentVisitor* visitor)
{
BOOST_FOREACH(equipment* anEquip, cont)
{
anEquip->accept(visitor);
}
visitor->visitComputer(this);
}
void visitFloppyDisk(floppyDisk* );
void visitProcessor(processor* );
void visitComputer(computer* );
Please explain using the example code i provided.
AFAIK, the first dispatch is happen on object who invoke the accept and second dispatch is happen on object who invoke the visit method.
Thanks.
In your example, you are missing the basics of the mechanism: inheritance and virtuality. Let's assume the following class hierarchy, in addition to your code:
Now, imagine you have this piece of code in some function:
Thanks to the double dispatch mechanism, this last line allows any
equipmentVisited
to accept anyequipmentVisitor
, no matter what their actual static types are. Eventually, the right function will be called for the right class.To summarise:
accept()
on the appropriate classIn short, single dispatch is when a method is polymorphic on the type of one parameter (including the implicit
this
). Double dispatch is polymorphism on two parameters.The typical example for the first one is a standard virtual method, which is polymorphic on the containing object's type. And the second one can be implemented via the Visitor pattern.
[update] I assume that in your example,
floppyDisk
,processor
andcomputer
each inherit from a common base class which definesaccept
as a virtual method. Similarly, thevisit*
methods should be declared virtual inequipmentVisitor
, which should have some derived classes with differentvisit*
implementations. [/update]Assuming the above,
accept
is polymorphic on boththis
andequipmentVisitor
. The floppydisk, processor and computer each have their own implementation ofaccept
, so when the visitor callsaccept
, the cal is dispatched based on the type of the callee. Then the callee calls back the visitor's type specific visit method, and this call is dispatched based on the actual type of the visitor.In theory there can be triple, quadruple etc. dispatch too, although I have never seen this implemented in practice (in languages that don't support double and higher dispatches by nature, that is - I seem to remember that Smalltalk does?). Double dispatch using Visitor in C++ and similar languages is already quite mind-boggling in itself, so the implementation of triple and higher dispatches would simply be too complicated to be used in real applications.