There’s been a lot of good discussion and debate recently about the idea of first class support for properties and events in Java 7 (possibilities include a new property keyword or a new -> syntax or even using annotations). I’m only mildly convinced that having properties and events in the language as first-class entities (presumably with the intention to support component-oriented programming) is worth doing. I’m particularly turned off by the -> syntax. Using annotations for this doesn’t seem worth the effort. Some more links can be found here: Danny Coward presentation that started this discussion, Rémi Forax, Stephen Colebourne, Kirk.
There are two places in Java that we have what I’ve heard Stuart Halloway call non-hygienic syntax. [The reference here is to hygienic macros in Scheme to basically mean macros that when expanded can’t break the meaning of the code they are used in.] Stu uses this term to describe syntax that doesn’t let the implementer of a component change their implementation without breaking the user of the component.
Example 1: Object Construction – Say I write an object called RockStar
and you new one up: RockStar singer = new RockStar("Mick Jagger");
But then later on I create a new class called AgingRockStar
and I really wish that I could return give my user an instance of AgingRockStar
instead of RockStar
. But, of course, I can’t unless my component’s caller changes his code. So, this is non-hygienic because a change on my side of the component requires a change to all of the callers of my component.
The standard way to avoid this issue is to use the factory method pattern (or abstract factory, etc). If you have a factory method that returns an interface or base class, the factory method is free to switch from returning RockStar
to returning AgingRockStar
or DeadRockStar
or whatever else it wants in response to inputs.
Example 2: Field Access – The other place you can see something like this is with Java fields (or in a stronger form, properties). If I create a class with a public field, I can set the value directly:
public class Payment { public int dollars; } Payment wasteCollectionBill = new Payment(); wasteCollectionBill.dollars = 20;
But say that your model becomes more complicated and you need to take into account that some Payments have kickbacks (maybe the Sopranos collect your garbage, for example). In that case, you may need to change it around a bit:
public class Payment { private int dollars; public void setDollars(int dollars) { extractKickback(dollars); this.dollars = dollars; } } Payment wasteCollectionBill = new Payment(); wasteCollectionBill.setDollars(20);
Notice that when you switch from using a field to a setter method, all calling code breaks and must be changed. Again, this is a non-hygienic syntax. This is such a pervasive problem that Java developers just code to the idiom that all class fields should be protected by getter/setter methods, which inevitably means more boilerplate code (which is so dumb your IDE can create it for you automatically).
I’m interested in the property proposal purely because it hints at a way to solve the issues in #2. If we were able to use a single syntax to mean either o.field or o.getField(), then we’re good. At that point, you can simply start with the field. Callers use the dot syntax and if you later decide a method is needed, then you can one without breaking those callers and they automatically redirected. This is also why I dislike the new -> operator suggestion. If we have to tell callers that this is happening, it ruins the whole point of doing it. I don’t see why they need to know or care whether they are accessing a field directly or going through a method. This class is a component with a data value and I want to get it.
Problem #1 is a little tougher I think. One way to cover this requirement (taken from other languages) is to allow an object constructor to return an object of a different class (but still type-compatible). This allows new to become a hygienic syntax as it can be much more flexible. I suspect that’d be quite a big change in both philosophy and semantics in Java, so I’m not holding my breath.