Coming from a java point of view, I still remember the disappointment the first time I realized that Java didn't have multiple dispatch. You know, the first time you realize that:
public static void a(Object o)
{
System.out.print("1");
}
public static void a(Number n)
{
System.out.print("2");
}
public static void main(String... args)
{
Object o = new Integer(3);
a(o);
a((Number) o);
}
...would write "12" instead of "22". (Of course, in functional languages this is taken even further with pattern matching)
I found more examples when looking at Slate, a Smalltalk-ish langage with this type of multiple dispatch (apparently development on the language is pretty much abandoned now though).
The advantages with multiple dispatch is discussed in the paper I linked to, but as a quick recap it allows you to push variant behaviour into different methods instead of using something like "instance of" or its variants.
Sure, it is possible to push back behaviour to the target object, but it is not always possible. Here is a standard "equals" method in java:
public boolean equals(Object otherKey)
{
if (this == otherKey)
{
return true;
}
if (otherKey instanceof Key)
{
Key key = (Key) otherKey;
return m_id == key.getId();
}
return false;
}
If java had multiple dispatch we could simplify this to:
public boolean equals(Key otherKey)
{
return m_id == key.getId();
}
public boolean equals(Object otherObject)
{
return false;
}
Which one is better should be pretty obvious.
There has been work on multiple dispatch for C++ that almost made it to C++0x, but apparently it came a bit too late to be included. CLOS and Dylan are the two languages usually mentioned in regards to multiple dispatch, but there is also support for it in Nice, the previously mentioned Slate, Cecil, Perl 6 and Groovy.