2

I'm trying to make my code more extensible for other devs by using Enums rather than an array of strings. I have:

public enum FOO {
   A, B, C, D, E
}

and

public enum BAR {
   Z, Y, X, W
}

In FOO I want to be able to define iteratively:

D, E, F(Z), F(Y), F(X), F(W)

So when I add items to BAR, it automatically adds it to FOO. I figure it has to be a method in FOO, and BAR should almost certainly be an inner class (thus private), but I've no idea how to do it. Using

for (BAR b : BAR.values()) {}

seems at least part of the solution. If it helps, for context, I'm using the Pathfinder RPG skills, with a list of each skill:

public enum SkillsEnum {
    ACROBATICS,
    APPRAISE,
    BLUFF,
    CLIMB,
    CRAFT,
    DIPLOMACY,
    DISABLE_DEVICE,
    DISGUISE,
    ESCAPE_ARTIST,
    FLY,
    HANDLE_ANIMAL,
    HEAL,
    INTIMIDATE,
    KNOWLEDGE(KnowledgeList.values().[0])
    KNOWLEDGE(KnowledgeList.values().[1]) etc
}
enum KnowledgeList {
     ARCANA,
     DUNGEONEERING,
     ENGINEERING,
     GEOGRAPHY,
     HISTORY,
     LOCAL,
     NATURE,
     NOBILITY,
     PLANES,
     RELIGION
}
Andrea
  • 12,296
  • 4
  • 32
  • 39
GrumpyTechDude
  • 103
  • 1
  • 8
  • Do you have to have multiple KNOWLEDGE SkillEnum? Can't you have 1 field with a list value. so when you add a new KnowledgeList, you add it to the KNOWLEDGE list. – Aboutblank Mar 05 '13 at 13:48
  • Why do you need a separate enum for knowledges, as opposed to adding `KNOWLEDGE_ARCANA`, `KNOWLEDGE_DUNGEONEERING` and so on to the main `SkillsEnum`? – Andrea Mar 05 '13 at 14:49
  • I figured that would be the fallback option, I just thought since all Knowledges will run on the same rules, it'd be a good "code reuse" situation. – GrumpyTechDude Mar 05 '13 at 15:29
  • Why did you try to corrupt my answer in this question [here](http://stackoverflow.com/questions/11093326/restricting-jtextfield-input-to-integers/11093360#11093360)? That's not much appreciated. – Hovercraft Full Of Eels Apr 06 '13 at 18:45
  • @HovercraftFullOfEels Your code was exactly what I was looking for, so I added it to my application. I found that you cannot remove the number completely, it wouldn't let you remove the first digit. The reason it was doing this was because an empty textbox would fail the test since 'Integer.parseInt("")' throws a numberFormatException, and thus the final character cannot be removed. I would have added a comment, but I think I need 2 more rep for that. I figured an empty text box isn't a bug, so submitted the edit for you to review, thinking I'd explained myself. Sorry if I missed the point. – GrumpyTechDude Apr 07 '13 at 12:07
  • Thank you for replying. Your edits would have ruined the code's use for its intended function, and so it was disallowed (by others before I even knew it had happened). In general you should not make substantial changes to someone else's answer unless you are a true expert in the field. – Hovercraft Full Of Eels Apr 07 '13 at 13:06
  • Ah, my apologies. Thanks for the insight though. – GrumpyTechDude Apr 07 '13 at 14:01

3 Answers3

1

Regarding adding items to BAR. Enum in Java are set of predefined constants, you should know their values at compile time. It is not possible to add items to ENUM at first place. Hope I have correctly interpreted your question.

Aman J
  • 1,825
  • 1
  • 16
  • 30
1

Enum instances are created magically by the C-like syntax public enum E { A, B, C } and you cannot add more instances, even if they would be known at compile time.

Depending on how much logic you have to attach to each enum instance and how many different "sub-enum" categories you have, you can try one of these approaches:

Single enum class with parameters

public enum Day {
    MONDAY(false),
    TUESDAY(false),
    WEDNESDAY(false),
    THURSDAY(false),
    FRIDAY(false),
    SATURDAY(true),
    SUNDAY(true);

    private final boolean weekend;

    private Day(boolean weekend) {
        this.weekend = weekend;
    }

    public boolean isWeekend() {
        return weekend;
    }

    public void doSomething() {
        if (isWeekend()) {
            // have fun
        } else {
            // do some work
        }
    }
}

Pros: this approach allows you to have a single enum class (so for example you can iterate easily on all instances), is simple, and adds no boilerplate.

Cons: if you test often for category membership your code will become cluttered with ifs; you cannot enforce at compile time that a variable refers to an instance of a specific category.

Enums implementing interfaces

public interface Day {
    public void doSomething();
}

public enum WorkDay implements Day {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY;

    @Override
    public void doSomething() {
        // do some work
    }
}

public enum WeekEnd implements Day {
    SATURDAY,
    SUNDAY;

    @Override
    public void doSomething() {
        // have fun
    }
}

Pros: you can have type safe references to instances of a single category; you can isolate category specific code in methods, reducing the need for membership tests; can be extended without modifying the original code.

Cons: requires some boilerplate (maybe too much for simple cases); you do not get an automatically generated collection of all instances.

See this answer for more examples of enums implementing interfaces.

Community
  • 1
  • 1
Andrea
  • 12,296
  • 4
  • 32
  • 39
0

I don't see a way for adding values dynamically to an enum. It's designed such that all values are known at compile time.

As an alternative, consider implementing enums yourself (using the Type safe enum design pattern). For example, "enum" B extends from "enum" A, and inherits all its values:

public class MyEnumA {
    private MyEnumA() {         
    }   
    public static MyEnumA a1 = new MyEnumA();
    public static MyEnumA a2 = new MyEnumA();
    public static MyEnumA a3 = new MyEnumA();
}

public class MyEnumB extends MyEnumA {
    private MyEnumB() {
        super();
    }   
    public static MyEnumB b1 = new MyEnumB();
    public static MyEnumB b2 = new MyEnumB();
    public static MyEnumB b3 = new MyEnumB();
}
Eyal Schneider
  • 22,166
  • 5
  • 47
  • 78