There are two problems here: one is that the code fails to work due to initialization issues, and the other is that you are having IDE problems. I'm going to address only the code failure.
The problem is that you need Empty()
run before you actually access Empty
, but accessing inner case objects doesn't run the initializer on the outer object since they're only pretending to be members of the inner object. (There is no variable inside Value
that holds Empty
.)
You can bypass this problem by running the apply()
method as part of the initializer for Empty
:
object Value extends Enum {
sealed abstract class Val extends EnumVal
case object Empty extends Val { apply() }
case object Player1 extends Val { apply() }
case object Player2 extends Val { apply() }
}
Now your initialization error should go away. (Because you have to do it this way, I suggest that apply()
is actually a bad choice of name; maybe set
or somesuch would be better (shorter).
If you stick the println
into a main
method, here's what the bytecode looks like for printing Value.values
:
public void main(java.lang.String[]);
Code:
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: getstatic #24; //Field WsTempA$Value$.MODULE$:LWsTempA$Value$;
6: invokevirtual #30; //Method Enum.values:()Lscala/collection/immutable/List;
9: invokevirtual #34; //Method scala/Predef$.println:(Ljava/lang/Object;)V
12: return
Note line 3, where you get a static field (which means that the JVM ensures that the field is initialized) for Values
itself. But if you go for Empty
you get
public void main(java.lang.String[]);
Code:
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: getstatic #24; //Field WsTempA$Value$Empty$.MODULE$:LWsTempA$Value$Empty$;
6: invokevirtual #28; //Method scala/Predef$.println:(Ljava/lang/Object;)V
9: return
Now line 3 refers not to Values
but to the inner object, which means the inner object's initializer gets called first, which then calls the outer object's initializer, which then sees that the inner object's initializer is supposed to be done (but it's actually not done)...and it calls a method on it and...boom.
If you put the apply
inside the Empty
initializer, you are saved because the Value
initializer, even though it's called out of order, doesn't call methods on Empty
any longer. So it miraculously works out. (Just make sure you don't introduce any other method calls!)