Kyle Sletten

The Open/Closed Dilemma

08 Aug 2014

Let's start with just a smidgeon of code I've been mulling over recently:

defa'a'enddefbaenda()#=> "a"b()#=> "a"defa'b'enda()#=> "b"b()#=> "b"

When you think about this example, it really shows the beauty of working in a
dynamic language. This is the kind of code that allows mocking to come much
more easily when everything is message based and dynamic. As a proud proponent
of static languages, I can't help but find this to be attractive and yet
dangerous. Like uncle Ben says: "With great power comes great responsibility."

In most static languages, that example is absolute rubbish. The compiler would
be SO upset with you for redefining a method because most static languages do
not perform lookups by name at runtime, so the only way to link properly is to
only allow one method definition with a given signature, right? I've been
thinking about that assumption, and I'm really beginning to think it's not true.
I'm thinking that something like this might be possible and even useful in a
static language by exploiting lexical scope. We all know how to read lexically
scoped code in static languages, but they let us redefine symbols in different
contexts to have different meanings, so what would this look like in say, Java?

The idea here is that in the context of PeopleByAge, the Person class compares
using the age property, while in the rest of the world they are compared by the
name property. This is useful enough, but the astute reader will know that
the TreeSet in particular can use a Comparator as one of its constructor
parameters to do this very thing. The advantage of having this dynamism is
that not all library authors will allow such a re-definition.

The really important part of selling this to static languages, I believe is the
distinction about what methods can be overridden and where. While Java uses
virtual dispatch for most (all?) of its method calls, one would not expect
someone to be able to override Person.getAge(). I tend to think that this could
be a great mechanism for re-implementing existing interfaces or even potentially
trying something like C# has to extend classes with new methods. I would even
take it one step further and say that it might be nice to be able to add an
interface to a class in such a lexically scoped way.

Ultimately this is not a serious proposal because it would require completely
overhauling the JVM, but it remains an interesting idea that I would love to
explore.