Robert Fischer over at enfranchisedmind.com has a post about anonymous inner classes which I am forced to disagree with quite strongly.
He starts off with the example of a comparator, and shows that defining a lambda and then casting it to a Comparator is terser. I largely agree. I don’t agree with everything about that example, but it would be churlish to quibble over details. I concede the point: For one method anonymous inner classes, lambdas are better.
He then attempts to generalise this to anonymous inner classes with multiple methods.
Except he doesn’t really. He simply states that because Groovy lets you coerce maps to an interface, you don’t need anonymous inner classes.
This is an interesting point. Let’s take it further.
We can define the following function (in some sort of pseudo syntax because I don’t know Groovy):
defineClass("Kitten", {
"meow" => () -> println("meow"),
"play" => it -> ...
})
Hopefully it will be taken as uncontroversial that I don’t consider this to be the best idea I’ve ever heard. There’s certainly a place for things like this – e.g. if you’re starting from a prototype based language like Javascript and want to build a class system on top of it, something like the above makes sense. But with classes baked into the language, I much prefer
class Kitten{
def meow = println("meow");
def play(it) = ...
}
It’s cleaner and terser syntax, and it better expresses the meaning.
So. We now have two ways of expressing classes which map to our two ways of expressing anonymous inner classes. Except that for some reason we prefer one in the named class case and one in the anonymous inner class case. This is odd, to say the least.
Now I want to pick a bone with the claim that what we’re really doing when we create anonymous inner classes is passing multiple functions. It seems utterly contrary to reality. That may be true in some cases when you’re using them as an argument to some method, but most languages I know have this interesting feature called “returning values from functions”. I know you don’t see it getting used much what with the current fad for writing all your programs in continuation passing style, but it does happen occasionally.
Consider example the following implementation:
class Vector[T]{
...
def elements = new Iterator[T]{
var position = 0;
def hasNext = position < length;
def next = {val it = this(position); position += 1; it }
}
}
This pretty unambiguously captures the intent: We’re creating a new iterator which captures the local scope. The alternative version (again, pseudo syntax):
class Vector[T]{
...
def elements = {
var position = 0;
{
"hasNext" => () -> position < length;
"next" => () -> {val it = this(position); position += 1; it }
} as Iterator
}
}
has absolutely no appeal to me. It muddies the intent and has worse syntax (if someone from the groovy world would like to tell me that the actual syntax for the above is better, please do, but I suspect I’ll still dislike even a slightly tider version of the above).
Iterators are one example, but there are plenty of others. e.g. in SBinary, formats have two methods read and write, and I return new ones as anonymous inner classes all the time. It would have been a maddening library to write without the capability to do that.
Anonymous inner classes get a bad reputation because so often their use is as a poor substitute for first class functions. But they really are a practically useful tool. I have plenty of other ideological reasons why I consider them vital to have, and this article was originally going to contain some of those, but I couldn’t be bothered. So I’m going to leave it at that: They’re useful, and they cleanly capture the intent in a way that I feel that coercing a map does not.