0

For the sake of clarity, I will do my best to frame the question through the lens of an example, rather than a code dump.

Before getting into my example, my question is as follows: How can I write a method that takes an enum as a parameter, and returns the static-information stored in an object (which inherits from a communal parent, where the static information is defined).

The example:

I am creating a game which includes many player-skills. These skills are created via an object tree, with the following inheritance (SomeSkill represents any of a dozen or so skills):

Skill > ActiveSkill > SomeSkill and Skill > PassiveSkill > SomeSkill

Psuedo-code for the class Skill:

    Class Skill{
       static string name = "Default Skill"
       int level;
       Skill(int level){
          this.level = level;
       }
       static getName{
          return name;
       }
    }

Name is static, since the name of the skill shouldn't change, regardless of the intance. In my actual implementation, Skill also includes static information description, and id.

Actual implementation of enum:

   public enum SkillType
   {
     basic, speed_buff, leap, beat_down
   }

The problem:

What I am struggling to do is write a method that takes a SkillType enum as an argument, and returns a usable Skill object (NOT an instance of the Skill object)

In Psuedo code: As an example, if I wanted to loop through the Enum and print out the names of all skills...

    method getSkillClass(SkillType skillType){
       if(skillType == beat_down) return BeatDown
       if(skillType == leap) return Leap
       ...
    }

    for(e : SkillType.getKeys){
       print(getSkillClass(e).getName);
    }

My current "solution" would be to create a map that matches SkillType to a list of instanced out Skills, with all non-static skill information set to default values.

This seems like an abuse of the system though.

How can I cleanly link my enum-list to the static information (the non-static information can be ignored) in my various skill classes?

SirLich
  • 79
  • 1
  • 12
  • How is SkillType different from Skill? And why have both? – Hovercraft Full Of Eels Oct 15 '18 at 01:30
  • Also, when you say *"returns a usable Skill object (NOT an instance of the Skill object"* how is a Skill object not an instance of Skill object? – markspace Oct 15 '18 at 01:32
  • *"Name is static, since the name of the skill shouldn't change, regardless of the intance."* Many Java strings are interned, meaning this "optimization" probably isn't doing much for you and is only causing your design to be more complicated. – markspace Oct 15 '18 at 01:35
  • Based on the names in your enum: `speed_buff, leap, beat_down` it sounds to me like you should apply some polymorphic method in your base Skill class and not try to re-invent the typing system by declaring these types of skills separately from the skills themselves. – markspace Oct 15 '18 at 01:37
  • I think my big "failure" was not realizing the full power of Enums. I use the SkillType Enum as a simple way to pass around skills in a plaint-text format. For example if I run the in-game command `/giveSkill speed_buff`, I can create a variable s = SkillType.valueOf("speed_buff"). I can now pass s around my functions as I handle the command. I should definitely look into a more powerful application of Enum that does not require this odd if/if/else linkage. – SirLich Oct 15 '18 at 04:50

2 Answers2

1

Java enums allow a constructor that can be used to associate data to the enum:

class Skill {
    ...
}

public enum SkillType {
    Basic(new Skill(...)),
    SpeedBuff(new Skill(...)),
    Leap(new Skill(...)),
    ...

    private final Skill skill;

    public SkillType(Skill skill) {
        this.skill = skill;
    }

    public Skill getSkill() {
        return skill;
    }
}

For further information, look at the 'Planet' example in the official enum documentation.

Alex Taylor
  • 8,343
  • 4
  • 25
  • 40
  • Thank you! This has definitely given me some food-for-thought. As I mentioned above, my biggest failure was not realizing the full power of Enums. Time to start refactoring! – SirLich Oct 15 '18 at 04:55
1

As @Alex mentioned, you can use enum constructor, but instead of creating an instance for linking, you can link the Class type if you don't want to create instances:

public enum SkillType {
    Basic(Basic.class),
    SpeedBuff(SpeedBuff.class),
    Leap(Leap.class),
    ...

    private final Class skillClass;

    public skillClass(Class skillClass) {
        this.skillClass = skillClass;
    }

    public Class getSkillClass() {
        return skillClass;
    }
}

You can then use reflection techniques to get the static field information as explained here.

Apoorv Agarwal
  • 336
  • 1
  • 7