Generic (parametrized) enums
Hi,
I have just read generics FAQ by Angelika Langer and I am wondering
why it is not allowed to have generic enums. I understand, that the only
problem is it doesn't make any sense to use a generic type in a static context
(at least in "normal" generic types). However, considering that it doesn't make
any sense to instantiate two (or more) the same enum types (and it is illegal),
it is perfectly safe to let static fields use type parameters. So I suppose the only
problem Sun had was how to implement it. That would probably caused a lot of
changes in the compiler implementation. What do you think about it ?
Cheers,
Adrian
# 4
It's not that I didn't understand something Stefan.
Have a look at this:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6408723
That seems to be reasonable, although it's got some drawbacks as well.
Now Angelika says true:
"Example (of an illegal generic enum type):
public enum Tag<T> { // illegal, but assume we could do this
good, bad;
private T attribute;
public void setAttribute(T arg) { attribute = arg; }
public T getAttribute() { return attribute; }
}
This enum type would be translated to a class that roughly looks like this:
public class Tag<T> extends Enum<Tag><T>> {
public static final Tag< ? > good;
public static final Tag< ? > bad;
private static final Tag $VALUES[];
private T attribute;
private Tag(String s, int i) { super(s, i); }
static {
good= new Tag("good", 0);
bad= new Tag("bad" , 1);
$VALUES = (new Tag[] { good, bad });
}
public void setAttribute(T arg) { attribute = arg; }
public T getAttribute() { return attribute; }
}
"
Let's see why it is a bad idea to use type parameters in static context:
MyClass<T> {
public static void doSomething(T t) {...}
}
...
MyClass<Integer> m1=new MyClass<Integer>();
MyClass<String> m2=new MyClass<String>();
MyClass.doSomething(?); // <-- what are we supposed to pass
// in here - Integer or String ?
Now one could say that we could do something like this:
MyClass.<String>doSomething(stringRef);
but it hasn't got much sense since we are not using the type parameter
taken from initialization of the class.
As for enums, what we could do is:
enum Tag<T> {
First<T>, Second<T>
}
which would be translated into something like this:
class Tag<T> extends Enum<Tag><T>> {
public static final Tag<T> First;
public static final Tag<T> Secons;
}
Why it would be possible ? How do we create enums ? We do:
enum Tag<String> {First<String>, Second<String>}
The point is, that we can't make another enum Tag - there is
only one class Tag, so we wouldn't be able to do something like this anyway:
enum Tag<Integer> {First<Integer>, Second<Integer>}
That's where we get type safety and are not interfering with static
context problem. The only problem to overcome would be to code
it somehow into a class by the compiler not to have this static context
problem (or treat it in a special way by the compiler, so it could say:
"ok - this is enum, so I allow to use class' type parameter in a static
context - but this is only here where it can be done.")
I hope that I have expressed what I wanted to say in a better way now ;)
Thanks,
Adrian
# 6
Hi,
Thanks for quick answer.
You are right - it doesn't make any sense. One could try to do it
that way:
public enum UserInfo<T> {
FirstName<T>,
LastName<T>,
UserSince<T>,
LastLogin<T>;
}
public <T> void setUserInfo( UserInfo<T> infoType, T infoValue ) {}
so you could call this method like:
setUserInfo(FirstName<String>, "Name"); // <-- that should be ok
setUserInfo(UserSince<Date>, "31/12/2003"); // <-- that should issue an error
but since you would have to explicitly provide the type, safety is no longer safe ... :/
And if you would be able to instantiate it like this:
public enum Something<String> {ONE, TWO, THREE}
then that would mean that all the static fields would have to be the same
type, which doesn't make any sense again ... (because as you said it's
not me who instantiate the class, but the compiler). We would have to have
some kind of a factory method there to be able to do such thing. I wonder
if that would help in any way ...
I give up - I couldn't expect to be smarter then the developers team at Sun ... ;)
Thanks for explanation and good point :)
Cheers,
Adrian