Re: final fields of an enum that refer to
Andreas Leitgeb wrote:
enum Thing {
T1, T2;
final Thing mate;
}
What could I do, to make T2 "final"ly the mate of T1
and vice versa ?
Strictly speaking, having each store a final Object reference to each
other is impossible, since a final variable is only set at construction,
and an object has to be created before it can be referred to. [1]
That does not preclude some workable alternatives. Possibilities that
would still work:
1. Make the mate a String. Because of the way enums work, you get the
same effect if you do |Thing.valueOf(mate)|.
2. If you drop finality, you can still initialize in the constructor.
Example:
enum Thing {
T1, T2(T1);
private Thing() { this(null); }
private Thing(Thing mate) {
this.mate = mate;
assert mate.mate = null;
mate.mate = this;
}
private Thing mate;
}
An enum initialization allows you to reference any variable declared to
the left of the current one but not anything to the right, so |T1(T2),
T2;| is impossible.
3. A less agreeable one, IMO. You can use some form of static-time
initialization, either manually setting the variables (ew?) or using a
map of some sort.
4. As you mentioned, you can also do abstract methods, but that seems
rather burdensome for such a feature.
[1] Well, if you let the |this| pointer escape initialization in a
controlled manner, and you have proper factory setup, it could be done:
public class Widget {
private Map<String, Widget> knownWidgets;
private final Widget(String qualifier, String mate) {
knownWidgets.put(qualifier, this);
this.mate = makeWidget(mate);
}
private final Widget mate;
public static Mate makeWidget(String qualifier) {
if (knownWidgets.get(qualifier))
return knownWidgets.get(qualifier);
String mate = /* determine this somehow */;
return new Widget(qualifier, mate);
}
}
That doesn't look too pleasant, is incomplete, and also violates the
dictum of not letting the |this| pointer escape the constructor. On the
other hand, it does show that it is possible in theory, but I think such
a setup would be rather fragile in actuality.
Such a model, furthermore, is difficult or probably even impossible to
emulate for enums, since they are the first things initialized in the
static initializer, and I think that either the compiler or the runtime
environment would complain if you started trying to play around with
them in the necessary clever ways.
--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth