Groovy and (Dynamic Dispatch|Multiple Dispatch|MultiMethods): A Simpler Example
So my last entry on static vs. dynamic dispatch and how it interacts with method overloading got caught up in some weird rules relating to the automatic promotion of primitive types. Now I have concocted an example that runs, unmodfied, in both Java and Groovy. Caution: This is a code heavy post.
public class BabyColors {
String color(Boy b) { return "Blue"; }
String color(Girl g) { return "Pink"; }
String color(Baby a) { return "Green"; }
String whatColor(Baby a) { return color(a); }
public static void testDirect() {
BabyColors bc = new BabyColors();
Baby a = new Baby();
Baby bb = new Boy();
Baby bg = new Girl();
Boy b = new Boy();
Girl g = new Girl();
bc.color(a);
bc.color(bb);
bc.color(bg);
bc.color(b);
bc.color(g);
}
public static void testIndirect(int iterations) {
BabyColors bc = new BabyColors();
Baby a = new Baby();
Baby bb = new Boy();
Baby bg = new Girl();
Boy b = new Boy();
Girl g = new Girl();
bc.whatColor(a);
bc.whatColor(bb);
bc.whatColor(bg);
bc.whatColor(b);
bc.whatColor(g);
}
public static void main(String[] s) {
BabyColors bc = new BabyColors();
Baby a = new Baby();
Baby bb = new Boy();
Baby bg = new Girl();
Boy b = new Boy();
Girl g = new Girl();
System.out.println("Indirect -------");
System.out.println("unknown - " + bc.whatColor(a));
System.out.println("baby boy - " + bc.whatColor(bb));
System.out.println("baby girl - " + bc.whatColor(bg));
System.out.println(" boy - " + bc.whatColor(b));
System.out.println(" girl - " + bc.whatColor(g));
System.out.println("Direct ---------");
System.out.println("unknown - " + bc.color(a));
System.out.println("baby boy - " + bc.color(bb));
System.out.println("baby girl - " + bc.color(bg));
System.out.println(" boy - " + bc.color(b));
System.out.println(" girl - " + bc.color(g));
}
}
class Baby {}
class Boy extends Baby {}
class Girl extends Baby {}
Seems simple enough, rather than using virtual methods to store the information as to what color a baby blanket you would buy for a co-workers new baby. If it's a buy, you get blue. If it's a girl, you get pink. Not sure? Green. The Baby color class keeps this information because, after all, babies don't know what color blanket they should have. You throw an old beach towel on some of them when they sleep and they will be happy (not that I've done this...).
Ok, back to the post. What will Java output? Think about this before you scroll down too far. Java looks a the types it can prove at compile time and fixes the method it will call based on the type the variable is claiming to be, not the type it actually is at run time. So when we filter all of the calls to color through an intermediary that only accepts Baby objects it will treat them as thought that's all they can ever be, Babys. Even if the compiler knows at the time that the call is being processed that the type must be a boy or a girl, it forgets all of that information when it goes into the whichColor method. Now when the color method is called directly, in the two instances where the type of the object is declared to be a Boy or a Girl the gender specific variant is called.
Now there is the dynamically typed method dispatch (or multiple dispatch, or multimethods) which on current generation JVMs is about a thousand times slower. Java itself doesn't support this invocation style, but Groovy supports this style as the only style of method invocation. At runtime when you invoke a method on an object, the actual instances of the types of the object are inspected and compared against all of the available overloaded method signatures. Hence regardless of the declared type of the object, the overloaded method that is selected will be closest to the particular class type and interfaces types of the passed in object.
So how do the languages process the above code? Well Java does the type safe thing and always buys green, unless it know it must be a boy or a girl.
Indirect -------
unknown - Green
baby boy - Green
baby girl - Green
boy - Green
girl - Green
Direct ---------
unknown - Green
baby boy - Green
baby girl - Green
boy - Blue
girl - Pink
Groovy on the other hand, peeks into the babies diaper and buys the appropriate color, unless it can't do that.
Indirect -------
unknown - Green
baby boy - Blue
baby girl - Pink
boy - Blue
girl - Pink
Direct ---------
unknown - Green
baby boy - Blue
baby girl - Pink
boy - Blue
girl - Pink