ifacethoughts

Single, Double And Multiple Dispatch

This post has already been published on code::gallery blog which now has been merged into this blog.

These are mechanisms in object oriented programming languages to identify the function/method to be invoked. The dispatch in the nomenclature is about dispatching messages to objects, as it is said in Smalltalk. It is equivalent of saying invoking methods of an object.

Single Dispatch

Typically, multiple methods or functions are given the same name, because the represent the same purpose. In the single dispatch mechanism, the method to be invoked is determined using the object, usually type of the object, on which it is invoked. It also includes the parameters, but the parameter types are identified at the compile time whereas dynamic binding or dynamic dispatch can be used for object on which method is invoked. This object is also syntatically highlighed, like obj.behave(the, arguments).

Most of the conventional and popular languages, like C++, Java or Smallatalk inherently support single dispatch mechanism.

Double Dispatch

Why is anything more than single dispatch is being considered? Because in the real world it is required. In the real world, the behavior between two objects is dependent on both of them and not just one. Lets consider an example.

Your behavior would change when you face other humans, the domestic cat or the tiger. This means that your actions are dependent not only on you but also on whom you face. This cannot be incorporated using the single dispatch mechanism.

So we come up with double dispatch. It is in fact a simulation using the single dispatch mechanism, and hence is not completely extensible.

The following code might not work, as pointed out by a commenter. Instead you can refer to Dr. Carlo Pescio’s explanation for more on this. It also goes a step further to improve the solution using templates.

I will try to update the following code to get it working.

Consider the following example code:

class Human;
class Cat;
	
class Animal
{
    public:
        virtual void face (Animal& animal);
        virtual void face (Human& human);
        virtual void face (Cat& cat);
}
	
class Human : public Animal
{
        virtual void face (Animal& animal)
        {
            animal.face(*this);
        }
	
        virtual void face (Human& human);
        {
            // shakehand
        }
	
        virtual void face (Cat& cat);
        {
            cat.face(*this);
        }
}
	
class Cat : public Animal
{
        virtual void face (Animal& animal)
        {
            animal.face(*this);
        }
	
        virtual void face (Human& human);
        {
            human.face(*this);
        }
	
        virtual void face (Cat& cat);
        {
            // run
        }
}

This code works. What is done here is that two calls are used to identify both the types involved. Consider this code:

Animal& acat = new Cat();
Animal& ahuman = new Human();
ahuman.face(acat);

Here, when ahuman.face(acat) is invoked, it in turn invokes Cat::face(Human&) at which point both the types are determined. This is the double dispatch mechanism.

However, as you can see, the biggest disadvantage is that the base class Animal has to know all the derived classes. Everytime a new animal is added, the interface of Animal has to change making it impractical, exactly what the Dependency Inverstion Principle advises us to avoid.

Multiple Dispatch

So we need multi dispatch, also called multimethods. The multidispatch mechanism considers all parameters equally and hence can provide easier and more extensible implementations. Some of the languages that support multiple dispatch are Common Lisp, Dylan, Nice, Scheme and Slate.

One of the common designs of multiple dispatch is to separate the methods from the class (which contains the structure). This allows for treating all the parameters equally.

Some of the conventional languages also support multimethods through extensions – Multimethods for Python, Multimethods for Perl, MultiJava, Ruby, C++ with Multimethods.

More reading:

Technorati tags: , , ,

Copyright Abhijit Nadgouda.

Discussion [Participate or Link]

  1. zaman bakshi said:

    The code is ridiculous and error-prone. Even if all the syntax errors are removed, it will not work.

  2. Abhijit Nadgouda said:

    Zaman, it probably is. I had tested it long back and probably not the exact code here. The aim of the code here was for illustration. Anyway, I will try to follow it up and come up with a piece that works.

  3. Deciding On Programming Languages | iface thoughts said:

    […] requirements can demand a specific programming style. A feature of functional programming is the multiple dispatch ability, which can make software development easier in some cases. An example that made rounds recently was […]

  4. Nicholas said:

    #include

    class Human;
    class Cat;

    class Animal
    {
    public:
    virtual void face(Animal & animal) = 0;
    virtual void face(Human & human) = 0;
    virtual void face(Cat & cat) = 0;
    };

    class Human : public Animal
    {
    public:
    virtual void face(Animal & animal);
    virtual void face(Human & human);
    virtual void face(Cat & cat);
    };

    class Cat : public Animal
    {
    public:
    virtual void face(Animal& animal);
    virtual void face(Human & human);
    virtual void face(Cat & cat);
    };

    ///////////////////////////////////////////

    void Human::face(Animal & animal)
    {
    animal.face(*this);
    }

    void Human::face(Human & human)
    {
    std::cout << “Human faces Human: Shakehand\n”;
    }

    void Human::face(Cat & cat)
    {
    std::cout << “Cat faces Human : eat?\n”;
    }

    void Cat::face(Animal & animal)
    {
    animal.face(*this);
    }

    void Cat::face(Human & human)
    {
    std::cout << “Human faces Cat: run?\n”;
    }

    void Cat::face(Cat & cat)
    {
    std::cout << “Cat faces Cat: shakehand\n”;
    }

    ///////////////////////////////////////////

    int main()
    {
    Animal & acat = * new Cat();
    Animal & ahuman = * new Human();
    ahuman.face(acat);
    return 0;
    }

Say your thought!

If you want to use HTML you can use these tags: <a>, <em>, <strong>, <abbr>, <code>, <blockquote>. Closing the tags will be appreciated as this site uses valid XHTML.

freshthoughts

contactme

Abhijit Nadgouda
iface Consulting
India
+91 9819820312
My bookmarks

badgesand...

This is the weblog of Abhijit Nadgouda where he writes down his thoughts on software development and related topics. You are invited to subscribe to the feed to stay updated or check out more subscription options. Or you can choose to browse by one of the topics.