I want to simplify the selection of a particular predefined object.
I currently have an enum defined as
ArtworkType { Poster, Banner, Other }
And I want to add attributes to those ArtworkTypes so that I can use them in code elsewhere. The attributes of the ArtworkTypes are either pre-defined static labels or populated from an external configuration file that is populated into a Properties() class.
Ideally I want to do something as simple as
ArtworkType.Poster.getWidth();
If I have to use a final class, I think it's going to be more complicated having to use something like
ArtworkType.getWidth(TypeEnum.Poster);
This is the sample enum code I've created so far (error checking 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;
}
}
While I appreciate this is against the principles of strict Enums, as the values that are associated with the Enum are static (for the duration of the application) it might be the lesser of two evils.
The only other approach that I can think of is to create an "ArtworkUtil" class that creates a collection and populates all the required attributes into an object and stores that in the collection.
Accessing that class in the code would make it a lot more unreadable (unless I'm missing something?)
Enums are compile-time constants. You can not initialize them from property files.
They can however have constructors, methods and fields. They can also have basic method implementations in the main body that are overwritten in the individual enum 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:
Shape: SQUARE, area: 100.00
Shape: RECTANGLE, area: 150.00
Shape: CIRCLE, area: 78.54
Shape: OVAL, area: 117.81
Enums are compile-time constants, so you can not initialize them using non-constant values, which means that you can't do this:
SQUARE(SomeClass.getSquareValue())
So you basically have three options:
Generate the enum automatically from your properties file
Use a build tool like Maven and have some code generate an enum file for you, converting this format:
ENUMNAME=property.value
into this enum entry:
ENUMNAME("property.value")
Add the generated enum .java to your compile sources. From the Java point of view, this is the cleanest approach, as you have absolute compile-time safety. The problem is: you need to re-compile every time the property file changes.
Lazy-initialize the enum (argh)
Initialize the enum items with property keys, and when the enum's method is first called, look up the property from the classpath, caching it for further use. This is an awful hack, but it is useful sometimes.
Pass all values into the enums from the outside, using them as strategy:
Example: this enum looks up System properties with a different prefix per enum entry.
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)
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With