2

I'm trying to define generic enum, but have problems with it:

private enum Stick<T>{
    A, B, C;

    private Stack<T> disks = new Stack();

    public void print(){
        System.out.println(this.name() + ": " + disks);
    }

    public T pop(){
        return disks.pop();
    }

    public void push(T element){
        disks.push(element);
    }

};

Is it possible at all?

Konstantin Milyutin
  • 11,946
  • 11
  • 59
  • 85

4 Answers4

12

Enums are constants. So Stack disks can not be "stack of whatever type the client of the enum wants". It has to be of fixed type.

The point of having fields in an enum is to be able to hold additional information about each element. For example, in the case of a stack, this could be A("a", "b"), B("b", "c", "d") - each element specify what items are loaded in its stack (the example requires a varargs constructor). But their type is strictly specified, it cannot be <T>.

The error that the eclipse compiler shows is clear:

Syntax error, enum declaration cannot have type parameters

However, you can do something like that:

enum Foo {
    A("foo", "bar"),
    B(0, 1, 2);
    private Stack<?> stack;
    private <T> Foo(T... args) {
        stack = new Stack<T>();
        stack.addAll(Arrays.asList(args));
    }
    public <T> Stack<T> getStack() {
        return (Stack<T>) stack;
    }
}

And then:

Stack<String> stack1 = Foo.A.getStack();
Stack<Integer> stack2 = Foo.B.getStack();

System.out.println(stack1);
System.out.println(stack2);

Results in:

[foo, bar]
[0, 1, 2]

Update: Since your comment about your goal - the hanoi towers should not be enums, because their values are changing. Instead, you should use the enums as keys to a Map, where the values are the stacks. I admit that it looks tempting to use a field of the enum to do that, but it is not a good practice. Enums better be constant. Of course, you can use my example above to achieve your initial goal, but I'd recommend a Map.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Thank you. I understand that enum is supposed to be constant. But technically speasking, it's the same class with fixed number of instances. So it should allow to use generics. – Konstantin Milyutin Sep 27 '11 at 15:56
  • @damular And what type should `T` be? You can't create an enum using the `new` operator, so how would you define the type of `T`? – Thomas Sep 27 '11 at 15:57
  • @damluar why do you want your sticks?stacks? to be enum constants? – entonio Sep 27 '11 at 16:01
  • I have three sticks with elements according to Hanoi game. That's why I want it to be enum + generic – Konstantin Milyutin Sep 27 '11 at 16:04
  • the hanoi stacks are changing. So you shouldn't use enums for them. You can use the enums as _keys_ to a map, where the value is the stack – Bozho Sep 27 '11 at 16:07
  • @Bozho Yes, I agree. But I thought that it's better to encapsulate all in one place, since enums are first-class objects – Konstantin Milyutin Sep 27 '11 at 16:09
  • @damluar - yes, it indeed looks tempting to put the changing fields in the enum, but it's not a good practice. – Bozho Sep 27 '11 at 16:12
  • 1
    @damular there's quite a design flaw if you put everything in one class. A stick is just that (a game element, or data) and should not have other responsibilities (like managing stacks), which should be handled by other classes (e.g. some manager class that handles a match instance etc.). – Thomas Sep 27 '11 at 16:12
  • @Thomas If you look at the code, there is no managing of stacks by sticks. It's just a wrapper – Konstantin Milyutin Sep 27 '11 at 16:18
0

There is a draft for generic enums here: http://openjdk.java.net/jeps/301

Hope it makes it into Java 10!

Leejjon
  • 680
  • 2
  • 7
  • 24
0

No, but Enums can implement interfaces. May be that helps you.

DerMike
  • 15,594
  • 13
  • 50
  • 63
0

This could help. Basically, you need this:

public interface Stick<E extends Enum<E>>
Community
  • 1
  • 1
Lucas
  • 14,227
  • 9
  • 74
  • 124