Create an Advanced Enumeration with Runtime Attributes

I want to simplify the selection of a specific predefined object.

I currently have an enum defined as

ArtworkType { Poster, Banner, Other } 

And I want to add attributes to these ArtworkTypes so that I can use them in code elsewhere. The ArtworkTypes attributes are either predefined static labels or are populated from an external configuration file, which is populated with the Properties () class.

Ideally, I want to do something as simple as

 ArtworkType.Poster.getWidth(); 

If I need to use the last class, I think it will be harder to use something like

 ArtworkType.getWidth(TypeEnum.Poster); 


EDIT: Thanks for the answers below, I come to the conclusion that while I can do this with Enum, it's probably better to use an external class (like ArtworkUtil) to retrieve the attributes that I need.

This is an example of the enumeration code that I have created so far (validation error omitted):

 public enum ArtworkType { Poster("poster"), Banner("banner"), Other("other"); private String type; private Dimension dimension; private ArtworkType(String type) { this.type = type; this.dimension = new Dimension(Properties.getProperty("width."+type), Properties.getProperty("height."+type); } public Dimension getDimension() { return dimension; } } 

Although I understand that this contradicts the principles of strict Enums, since the values ​​associated with Enum are static (at the time of application), it can be less than two evils.

The only other approach I can come up with is to create the "ArtworkUtil" class, which creates a collection and fills all the necessary attributes into an object and stores them in the collection.

Access to this class in code will make it much more unreadable (unless I miss something?)

+4
source share
3 answers

Enumerations are compile-time constants. You cannot initialize them from property files.

However, they may have constructors, methods, and fields. They can also have basic implementations of methods in the main body that are overwritten in separate enumeration entries.

 public enum Shape{ SQUARE(10), RECTANGLE(10, 15), CIRCLE(10){ @Override public double getArea(){ return Math.PI * Math.pow(((double) getWidth()) / 2, 2); } }, OVAL(10, 15){ @Override public double getArea(){ return Math.PI * (getWidth()) / 2 * (getHeight()) / 2; } }; private Shape(final int dim){ this(dim, dim); } private Shape(final int width, final int height){ this.width = width; this.height = height; } private final int width; private final int height; public double getArea(){ return width * height; } public final int getWidth(){ return width; } public final int getHeight(){ return height; } } 

Test code:

 public static void main(final String[] args){ for(final Shape shape : Shape.values()){ System.out.printf("Shape: %s, area: %1.2f\n", shape, shape.getArea()); } } 

Output:

Form: AREA, area: 100.00
Form: DIRECT, area: 150.00
Form: CIRCLE, area: 78.54
Form: OVAL, area: 117.81


Work with compile time limits

Enums are compile-time constants, so you cannot initialize them using mutable values, which means you cannot do this:

 SQUARE(SomeClass.getSquareValue()) 

So, you have three options:

  • Create an enumeration automatically from your properties file

    Use a build tool such as Maven, and you have the code to generate the enumeration file for you, converting this format:

     ENUMNAME=property.value 

    to this listing entry:

     ENUMNAME("property.value") 

    Add the created enum.java to your compilation sources. From a Java perspective, this is the cleanest approach since you have absolute security at compile time. The problem is this: you need to recompile every time you change the properties file.

  • Lazy-initialize enum (argh)

    Initialize enumeration elements using property keys, and when the enum method is first called, find the property from the class path, caching it for future use. This is a terrible hack, but sometimes it is useful.

  • Pass all the values ​​to the enums from the outside, using them as a strategy:

    Example: this enumeration looks at system properties with a different prefix for each enumeration record.

     public enum Lookup{ ADDRESS("$1".address), NAME("$1".name); private final String pattern; private Lookup lookup(String pattern){ this.pattern=pattern; } public final String lookupProperty(String input){ return System.getProperties().get( this.pattern.replace("$1",input) ); } } 
+13
source
 public enum ArtworkType { Poster, Banner, Other; private static ResourceBundle properties; private static ResourceBundle getProperties() { if( properties == null ) { properties = ResourceBundle.getBundle( "artworks"); } return properties; } public int getWidth() { return Integer.parseInt( getProperties().getString( "width."+this.name() ) ); } } 

This is a rough idea of ​​what you need to do. Of course, this is not really a product quality code; some safety measures were omitted for readability.

And your properties file will be something like this:

artworks.properties

 width.Poster=500 width.Banner=1900 width.Other=-1 
+2
source

If you want to use the getWidth () method, you can add it to the enumeration just like any other type of class. Perhaps you could clarify your concern.

From the enum documentation

 public enum Planet { MERCURY (3.303e+23, 2.4397e6), VENUS (4.869e+24, 6.0518e6), EARTH (5.976e+24, 6.37814e6), MARS (6.421e+23, 3.3972e6), JUPITER (1.9e+27, 7.1492e7), SATURN (5.688e+26, 6.0268e7), URANUS (8.686e+25, 2.5559e7), NEPTUNE (1.024e+26, 2.4746e7), PLUTO (1.27e+22, 1.137e6); private final double mass; // in kilograms private final double radius; // in meters Planet(double mass, double radius) { this.mass = mass; this.radius = radius; } public double mass() { return mass; } public double radius() { return radius; } // universal gravitational constant (m3 kg-1 s-2) public static final double G = 6.67300E-11; public double surfaceGravity() { return G * mass / (radius * radius); } public double surfaceWeight(double otherMass) { return otherMass * surfaceGravity(); } } 
0
source

Source: https://habr.com/ru/post/1337482/


All Articles