Classic Java Method Dispatching Anger

Posted by Anders Fri, 18 May 2007 23:20:00 GMT

On a common trap that a lot of us have walked into as our Java skills deepened:

You’re solving some programming problem involving multiple types/classes when you realize that you can make great use of Java’s method overloading. Just implement one method for each of the classes, and you’re done! In this example, two subclasses of Person:

void doStuff(Worker worker) {
   ...
}
void doStuff(Capitalist capitalist) {
   ...
}

Now if you just call doStuff like this:

Person person = ...
x.doStuff(person);

it should all work, right? It should call the correct method, depending on which class person is. You probably feel a slight rush of pride when you look at how simple your solution is.

But of course it doesn’t work. Java’s method calls must have their argument types known at compile-time1. You need to have person cast to one of the subclasses, otherwise the compiler will complain that it doesn’t know which of the two methods you mean. You mean “either”, but the compiler can’t help you.

At this point there is often bitter disappointment and anger, usually directed at the compiler or language (“jävla skitspråk!”). Once that subsides, you know you have learned something. Even programmers with good knowledge of Java seem to walk into this trap, which is what made me notice this phenomenon. Even though you know all the theory of how Java works, you can still get surprised by the practical implications.

For me, it was around 1999 at my first job. I can’t remember the problem I was trying to solve, but I do remember the surprise and disappointment. I last witnessed it just a few weeks ago. When I mentioned the phenomenon to a friend, he recalled having gone through it himself, and also having witnessed it recently.

Does everyone go through this when they’re learning Java?

1 This doesn’t happen with dynamically typed languages, since they typically bind their methods at run-time. On the other hand most dynamically typed languages don’t do method dispatching on types at all. Some functional languages with fancier method dispatchers can do this stuff, maybe at the expense of slower method calls. Erlang’s pattern matching of messages takes this feature to the extreme (though it’s not exactly method calls). You could argue that Prolog is the very extreme of this, where everything is fancy method dispatching.

Posted in ,  | Tags ,  | 3 comments

Comments

  1. Dan said about 21 hours later:
    Hi Anders, one solution to this particular problem is to use double dispatch (http://en.wikipedia.org/wiki/Double_dispatch). This a neat trick that will give you the kind of polymorphic behaviour you are looking for without the need for any instanceof checks.
  2. Johan Lind said 8 days later:
    Remember that the double dispatch pattern i patented in the US to John Vlissides/IBM.. :) http://www.patentstorm.us/patents/6721807.html
  3. Anders Grusell said 11 days later:
    Haha, I have been there too... And I always use double dispatch since then. I like the CLOS/Lisp approach to the problem where methods are not grouped by class at all but by generic functions, and therefore in CLOS methods are separate from data, which mean you can change or even add methods at runtime without changig the objects that you currently have in the system. So many workarounds you see in the form of design patterns that are alrady solved years ago in Lisp...

Comments are disabled