views:

66

answers:

2

I am constructing enum values that have a data structure like the following:

enum MetaType {
 HUMAN(
  new MetaTypeAttribute(AttributeType.BODY, 1, 6),
  new MetaTypeAttribute(AttributeType.AGILITY, 1, 6),
  new MetaTypeAttribute(AttributeType.REACTION, 1, 6)
 ),
 ORK(
  new MetaTypeAttribute(AttributeType.BODY, 4, 9),
  new MetaTypeAttribute(AttributeType.AGILITY, 1, 6),
  new MetaTypeAttribute(AttributeType.REACTION, 1, 6)
 );

 MetaType(MetaTypeAttribute body, MetaTypeAttribute agility, MetaTypeAttribute reaction) {
 }
}

So there is an enum of MetaTypes; each MetaType specifies a fixed set of MetaTypeAttributes, which consist of a min and max value for that attribute.

I hate this syntax. It's too long, it's ugly, and it doesn't prevent me from passing in the wrong AttributeType (the AttributeType should match up with the order of the arguments of MetaType's constructor; AttributeType.BODY > body, etc.). What I want is a better pattern for ensuring that an object is constructed with this exact scheme.

This code is abbreviated. In reality there are 9 AttributeTypes.

Any suggestions for improvement?

A: 

If you consider different attribute types, maybe you should really create those attribute types as classes/subclasses instead of enums. You will have all the advantages of OOP to handle the behavior of each type (inherited methods, method rewriting, ...) and they'll be type safe.

abstract class AbstractTypeAttribute{
    private final int min, max;
    public AbstractTypeAttribute(int min, int max){
        //...
    }
    //...
}

class Body extends AbstractTypeAttribute{
    public Body(int min, int max){
        super(min, max);
        //...
    }
    //...
}

You should think about doing this instead of meta attributes and meta types too.

Colin Hebert
You can inherit and overwrite methods with enums too. And enums are fully type safe. I don't see an advantage here. Your approach does not provide constants, btw.
Willi
You can't inherit enums, they are de facto final. Enums are type safe, but not enum content, it can't be used as a type. I don't know about what constants you're talking about.
Colin Hebert
+1  A: 
    enum MetaType {
 HUMAN(new MyRange(1,1), new MyRange(1, 10), new MyRange(1,10)
 ),
 ORK(new MyRange(1,1), new MyRange(1, 10), new MyRange(1,10)
 );

 MetaType(MyRange body, MyRange agility, MyRange reaction) {
      this.bodyAttrib = new MetaTaypAttibute(AttributeType.BODY, body);
      this.agilityAttrib = new MetaTaypAttibute(AttributeType.AGILITY, agility);
      this.reactionAttrib = new MetaTaypAttibute(AttributeType.REACTION, reactiony);}
}
mohammad shamsi
Thanks! I ended up using this pattern. Strictly speaking, I don't need the MetaTypeAttribute object when I do it this way; I just store a Map<AttributeType, Range> which is populated from the constructor args.
RMorrisey