Regarding alternative to interfaces and acessing with static imorts - java

I was going through a research in which I dont want to store the constants in the interface itself, so I was looking for alternatives like enums but another approach I have found is that ....t instead of using an interface, use a final class with a private constructor. (Making it impossible to instantiate or subclass the class, sending a strong message that it doesn't contain non-static functionality/data. and we can also take the advantage of static import in that case
Public final class KittenConstants
{
private KittenConstants() {}
public static final String KITTEN_SOUND = "meow";
public static final double KITTEN_CUTENESS_FACTOR = 1;
}
two independent things. 1: use static imports instead of abusing inheritance. 2: If you must have a constants repository, make it a final class instead of an interface . Please advise is this approach is correct..!!
To avoid some pitfalls of the constant interface (because you can't prevent people from implementing it), a proper class with a private constructor should be preferred (example borrowed from Wikipedia):
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
And to access the constants without having to fully qualify them (i.e. without having to prefix them with the class name), use a static import (since Java 5):
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
Please show how we can do same ting with enum also..!

You can achieve your "constants" via an enum:
public enum Animal {
Kitten("meow", 1),
Puppy("woof", 2);
private final String sound;
private final double cuteness;
Animal (String sound, double cuteness) {
this.sound = sound;
this.cuteness = cuteness;
}
public String getSound() {
return sound;
}
public double getCuteness() {
return cuteness;
}
}
To use:
String sound = Animal.Kitten.getSound();
double cuteness = Animal.Kitten.getCuteness();

The simple answer is that you can't do that with an enum. An enum defines a set of related constants with the same type.
What you have in the KittenConstants case is a set of constants with fundamentally different types. This doesn't fit the enum model. (If you change the problem a bit; e.g. by generalizing over different kinds of SFA, you can make it fit ... as #Bohemian does ... but if that's not what you are trying to achieve, enum is not the right solution.)
What you have in the Constants case is a bunch of named floating point constants that you want to use as values. (All the same type ... which helps!) Now you could declare them as an enum as follows:
public enum Constants {
PLANCK_CONSTANT(6.62606896e-34),
PI(3.14.59);
public final double value;
Constants(double value) {this.value = value);
}
The snag is that you need to use ".value" to access each named constant's numeric value; e.g.
import static Constants.*;
....
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT.value / (2 * PI.value);
}
.... which is kind of ugly, and I don't think there is any way around the ugliness.
Bottom line - enums are not an ideal replacement for all kinds of constant.

Related

Is it the best option to convert a java interface with static fields in a abstract class in c#?

public interface IHashStorage<T> {
public static final float INITIAL_LOAD_FACTOR = 0.7f;
public static final int INITIAL_CAPACITY = 149;
}
I have the code above which needs to be translated in c#. The only solution that seems to be proper is to make it an abstract class.From what I found it's safer to use readonly than const:
public abstract class IHashStorage<T>
{
private readonly float INITIAL_LOAD_FACTOR = (float)0.7;
private readonly int INITIAL_CAPACITY = 149;
}
The project in Java is using the Decorator pattern and Proxy, the transformation from java to c# can possibly require to use more abstract classes(currently in java there are only interfaces used)?I know theoretically the difference between them but practically in c# I used abstract classes more.I'm not that familiar with java and I would like to know your advice about how to find the best solution to finish this task, I mean the main points to keep in mind when converting the code.
I would define an interface with a get property.
then, make my base class implement it and set the default values
and then, extend the base class for every java class that implements the java interface.
something along these lines:
public interface IHashStorage<T>
{
float InitialLoadFactor { get; }
int InitialCapacity { get; }
}
public class HashStorageBase<T> : IHashStorage<T>
{
private readonly float _initialLoadFactor = 0.7f;
private readonly int _initialCapacity = 149;
public float InitialLoadFactor
{
get { return _initialLoadFactor; }
}
public int InitialCapacity
{
get { return _initialCapacity; }
}
}
public class HashStorage1<T> : HashStorageBase<T>
{
...
}
As I imply in my comment, there is no way to attach fields (or any other implementation details) to an interface in C#. You have two options besides making this an abstract class:
Make the fields into (probably read-only) properties on the interface, which will force all implementations to specify them.
Make the fields into custom attributes defined on the interface and/or the implementions.

Enums as replacement of Constants in Java

I heard now a day that We should use Enums instead of Constants .
Is it possible in all cases ? Whether enums are replacement of Constants ?
In Below Example I have Constants defined in Constants file and ConstantsTest uses them
public final class Constants {
private Constants(){
}
public static final String ACCOUNT="Account";
public static final String EVENT_ITEM ="EventItem";
public static final int MULTIPLIER_ONE = 1;
public static final int MULTIPLIER_NEGATIVE_ONE = -1;
public static final String BALANCE_AFTER_MODIFICATION = "BalanceAfterModification";
public static final String COMMA = ",";
public static final String DOTPSV =".psv";
public static final String NEW_LINE = "\n";
}
// Test Class
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class ConstantsTest {
private static File rootDir = new File(".");
public static void main(String[] args) throws IOException {
Map<String,Integer> accountBalance = new HashMap<String, Integer>();
accountBalance.put("123",55000);
accountBalance.put("223",15000);
writeToFile(Constants.ACCOUNT, accountBalance, true, 2000);
// do operation
}
/**
*
* #param fileType
* #param inputData
* #param add if true add balance else substract the balance
* #return
* #throws IOException
*/
private static File writeToFile(String fileType , Map<String,Integer>accountBalance ,boolean add, int amount) throws IOException{
File file = null;
FileWriter fw = null;
try{
if(Constants.ACCOUNT.equals(fileType)){
file = new File(rootDir,Constants.ACCOUNT+Constants.DOTPSV);//creating a fileName using constants
fw = new FileWriter(file);
fw.write(Constants.ACCOUNT+Constants.COMMA+Constants.BALANCE_AFTER_MODIFICATION);//Writing Header in file using constant values
updateBalance(accountBalance, add, amount);
for(String key:accountBalance.keySet()){
fw.write(Constants.NEW_LINE);
fw.write(key+Constants.COMMA+accountBalance.get(key));
}
}
else if(Constants.EVENT_ITEM.equals(fileType))
{
// write to EventItem.psv
}
} finally{
if (null!=fw){
fw.close();
}
}
System.out.println("File created successfully");
return file;
}
private static void updateBalance(Map<String, Integer> accountBalance,
boolean add, int amount) {
for(String key:accountBalance.keySet()){
int currentBal = accountBalance.get(key);
if(add){
accountBalance.put(key,currentBal+amount*Constants.MULTIPLIER_ONE); // do lot of calculations
}else{
accountBalance.put(key,currentBal+amount*Constants.MULTIPLIER_NEGATIVE_ONE);// do a lot of calculations
}
}
}
}
Please suggest in my sample example enums would be better or my current approach of using constants is good enough ?
In your particular case the using enums is classic solution.
First, let's re-write your Constants as an enum:
public enum Constants {
ACCOUNT,
EVENT_ITEM,
;
}
public enum Operation {
MULTIPLIER_ONE {
public int action(int value) {
return value;
}
},
MULTIPLIER_NEGATIVE_ONE {
public int action(int value) {
return value * (-1);
}
},
;
private Operation(int coef) {
this.coef = coef;
}
public abstract int action(int value);
}
Now instead of writing:
if(Constants.ACCOUNT.equals(fileType)){
} else if(....)
you can either use switch/case or even better define: define method (let's call it action() into the enum and call it from your code. See example in Operation enum above. In this case you code becomes trivial: no more if/else or switch statements. Everything is simple. Validation is done at compile time: you defined abstract method in enum you cannot add yet another element to enum without implementing this method for it. This does not happen when using if/else structures maintenance of which is a programmer's responsibility.
I know only one limitation of enums: using string contstants in annotations. There are a lot of annotations with string attributes. For example XmlElement(name="foo"). Even if you define enum
enum FooBar {
foo, bar
}
you cannot use it in annotations:
#XmlElement(name=FooBar.foo) // is wrong because String type is required
#XmlElement(name=FooBar.foo.name()) // is wrong because annotations do not support method invocation
In all other cases I prefer enum.
You should use enums this code
enum Constants {
ACCOUNT,
EVENT_ITEM ,
COMMA ,
DOTPSV ,
BALANCE_AFTER_MODIFICATION ;
#Override
public String toString() {
switch(this) {
case ACCOUNT: return "Account";
case EVENT_ITEM : return "EventItem";
case COMMA : return ",";
case DOTPSV : return ".psv";
case BALANCE_AFTER_MODIFICATION : return "BalanceAfterModification";
default: throw new IllegalArgumentException();
}
}
}
Only we can use Enums for the constant values which are in the single group.
Let us suppose: Weeks, Months, Colours, Gender, Process states
It is not the good idea to use single enum for storing all constants. Instead we can use one enum for each group of constants.
Let us suppose you have maintaining some colour codes then better to have Colour enum instead of saving as constants.
An Enum doesn't define a contract for the class using it, an interface does. A class which uses an Enum isn't of the type an Enum. A class which implements an Interface is effectively of the same type as the interface (the Interface is the parent.. and the reference could be changed). Considering these design issues. Tell me, is your approach correct?
You got enum wrong, it's not like you should create an enum instead of constant: an enum is a group of constants that are related, for example:
enum Days {
SUNDAY, MONDAY, TUESDAY, ...
}
From the docs:
An enum type is a special data type that enables for a variable to be
a set of predefined constants.
Constants will be better for the example provided. Interface variables are public static final by default.
public static final String ACCOUNT="Account";
See Why are interface variables static and final by default?

Are enums less maintainable than public static final constants?

I was recently discussing enums vs public static final constants with a friend. I told him that public static final constants are more maintainable than enums, sometimes faster (android developer docs confirm this), and more convenient as well. I also said that you lose functionality when using enums as well:
You cannot extend an enum.
You cannot instantiate an enum.
He then said you shouldn't be using an enum if you need to instantiate or extend an enum. I then replied that's why we should just use constants because it is more maintainable; What if mid project we need to instantiate an enum or extend it? Then we would have to change everything.
An example demonstrating enums vs constants I made to illustrate my point:
public enum WeekDay {
/*
* We will start at 1 for demonstration
*/
SUNDAY("Sunday", 1), MONDAY("Monday", 2), TUESDAY("Tuesday", 3), WEDNESDAY(
"Wednesday", 4), THURSDAY("Thursday", 5), FRIDAY("Friday", 6), SATURDAY(
"Saturday", 7);
/*
* Notice we cannot do this...This is where enums fail.
*/
// LUNES("lunes",1), MARTES("martes",2);
private String dayName;
private int dayIndex;
private WeekDay(String dayName, int dayIndex) {
this.dayName = dayName;
this.dayIndex = dayIndex;
}
public String getDayName() {
return dayName;
}
public void setDayName(String dayName) {
this.dayName = dayName;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
#Override
public String toString() {
return this.dayName + ": " + this.dayIndex;
}
}
What if we need Spanish week days as well? The enum falls short because you cannot extend it (you would have to do some copy and paste action).
Contrast the enum with this:
public class WeekDayClass {
private int dayIndex;
private String dayName;
public WeekDayClass(int dayIndex, String dayName) {
super();
this.dayIndex = dayIndex;
this.dayName = dayName;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
public String getDayName() {
return dayName;
}
public void setDayName(String dayName) {
this.dayName = dayName;
}
#Override
public String toString() {
return this.dayName + ": " + this.dayIndex;
}
abstract static class Constants {
}
public static void main(String[] args) {
WeekDayClass init = new WeekDayClass(10, "I can init new days here");
}
}
And then I can extend it and make AmericanWeekDays:
public class AmericanWeekDay extends WeekDayClass {
public AmericanWeekDay(int dayIndex, String dayName) {
super(dayIndex, dayName);
}
static class AmericanConstants extends Constants {
public static final WeekDayClass SUNDAY = new WeekDayClass(1, "Sunday");
public static final WeekDayClass MONDAY = new WeekDayClass(2, "Monday");
/*
* And so on...
*/
}
}
Or Spanish Week Days:
public class SpanishWeekDays extends WeekDayClass {
public SpanishWeekDays(int dayIndex, String dayName) {
super(dayIndex, dayName);
}
static class SpanishConstants extends Constants {
public static final SpanishWeekDays LUNES = new SpanishWeekDays(2, "lunes");
/*
* And so on...
*/
}
}
Also to go even further:
public class WeekDayClass {
private int dayIndex;
private String dayName;
public WeekDayClass(int dayIndex, String dayName) {
super();
this.dayIndex = dayIndex;
this.dayName = dayName;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
public String getDayName() {
return dayName;
}
public void setDayName(String dayName) {
this.dayName = dayName;
}
#Override
public String toString() {
return this.dayName + ": " + this.dayIndex;
}
static class AmericanConstants {
/*
* Insert Constants Here
*/
}
static class SpanishConstants {
/*
* Insert Constants Here
*/
}
}
I understand with an enum you could perhaps make a workaround using data structures (Lists) so you accommodate this shortcoming but why bother? With using public static constants I gain inheritance from the base class, cleaner code, possibly shorter code, and easier maintainability.
I also read that you can use enum's to better design "input parameters" but you could also do the same with the public static final constants as shown above.
Enums have the advantage of being able to be used in switch statements and have the inherited enum methods like values(). These methods can also be replicated if needed in "public static final constant" classes. Aside from the switch I don't see any enum advantages.
In conclusion, is an enum really better than public static final constants? If so, where did I go wrong? Is their something I am missing?
EDIT:
You cannot use generics in enums as well.
Enums get you a lot more than you seem to give them credit for, and while sometimes constants are required, this case is probably a win for enums.
First of all, there is no real difference between an "English weekday" and a "Spanish weekday", they represent the same values. Therefore, the best solution would be to do the conversion to string independently of what the values actually are through some kind of localization method. The values don't change with the language, their representation does.
This is entirely doable quickly and easily with enums. Just write it like this (a little pseudocode-y):
public enum Weekday {
MONDAY,
TUESDAY,
WEDNESDAY,
...;
public String toLocalizedString(Language l) {
// interact with localization files
}
}
You are conflating the ideas of external representation and internal representation. Your data should be as homogenous as possible because there is only ever going to be one Monday. It might be called different things, but it's still the same value.
Enums also get you a lot of niceness for free, though, which makes your code much clearer and more maintainable in the long run. Type checking, == comparison, and usability in switch are a few, with no boilerplate to speak of.
I think you're taking the usage of enums way to far and then come to a conclusion that they are not useful.
Enums are simply telling you that there's a limited and predefined number of options to choose from. Nothing more than that. For example, when you see a parameter that is an enum (let's say State) and it has 3 values (Pending, InProgress, Closed), you know that a state of some object can have one of those and only one of those values.
Enums provide an easy way of validating that a proper value is used as you cannot easily select a value that is not proper when coding. They are also a way of documenting as you can easily see what options are available.
Enumerations wouldn't exist if they weren't useful - the same can be said of constants. Just like a screwdriver can remove a screw while a hammer can remove a nail - different tools in your programmer "toolbox" can be used for unique and important purposes. I suggest reading more about enumerations and constants and I think you will find why they exist and when to use them.

How to use Java Enums being DRY with only a single parameter different between instantiations?

I'm trying to figure out if there is a clean way of doing this. I want to design an ENUM to maintain a list of constant values for different components in my application. Each enum would have the same configuration and same parameters, but would differ at the very least by component name.
In a normal Java class, I could build all the basic logic/code in a base abstract class, and have each component constants extend the abstract class and populate only its own pertinent information. However, Java enums do not allow extending existing classes.
Is there something I can do to avoid having to either push all my constants in a single Enum (ugggg!) or recreate the same enum class each time for each differing component? Definitely not DRY in that case, but I do not know how to avoid the issue.
For a quick use-case example off the top of my head. Say I want to keep a list of all my request mappings in an Enum for use elsewhere in my application. Fairly easy to design an enum that says:
public enum RequestMapping {
INDEX("index"),
GET_ALL_USERS( "getAllUsers");
private String requestMapping = "/users";
private String path;
RatesURI( String path ){
this.path = path;
}
public String getRequestMapping(){
return requestMapping;
}
public String getPath(){
return path;
}
public String getFullRequestPath(){
return requestMapping + "/" + path;
}
}
It becomes easy to use RequestMapping.GET_ALL_USERS.getFullRequestPath().
Now if I want to create this enum on a per-controller basis, I would have to recreate the entire Enum class and change the "requestMapping" value for each one. Granted, this enum has nearly no code in it, so duplicating it would not be difficult, but the concept still remains. The theoretical "clean" way of doing this would be to have an abstract AbstractRequestMapping type that contained all the methods, including an abstract getRequestMapping() method, and only have the extending Enums implement the controller-specific getReqeuestMapping(). Of course, since Enums cannot be extended, I can't think of a non DRY way of doing this.
Have you considered extending a class that takes Enum as a generic parameter? It is an amazingly flexible mechanism.
public class Entity<E extends Enum<E> & Entity.IE> {
// Set of all possible entries.
// Backed by an EnumSet so we have all the efficiency implied along with a defined order.
private final Set<E> all;
public Entity(Class<E> e) {
// Make a set of them.
this.all = Collections.unmodifiableSet(EnumSet.<E>allOf(e));
}
// Demonstration.
public E[] values() {
// Make a new one every time - like Enum.values.
E[] values = makeTArray(all.size());
int i = 0;
for (E it : all) {
values[i++] = it;
}
return values;
}
// Trick to make a T[] of any length.
// Do not pass any parameter for `dummy`.
// public because this is potentially re-useable.
public static <T> T[] makeTArray(int length, T... dummy) {
return Arrays.copyOf(dummy, length);
}
// Example interface to implement.
public interface IE {
#Override
public String toString();
}
}
class Thing extends Entity<Thing.Stuff> {
public Thing() {
super(Stuff.class);
}
enum Stuff implements Entity.IE {
One,
Two;
}
}
You can pass the nature of your implementation up to the parent class in many different ways - I use enum.class for simplicity.
You can even make the enum implement an interface as you can see.
The values method is for demonstration only. Once you have access to the Set<E> in the parent class you can provide all sorts of functionality just by extending Entity.
I will probably split the responsibilities into two parts:
Logic about how a request is structured, and put that into an immutable class.
Actual configurations of each request, stored in enums
The enum will then store an instance of that class, you can add new methods to the class, without modifying the different enums, as long as the constructor remains the same. Note that the class must be immutable, or your enum will not have a constant value.
You can use it like the:
ServiceRequest.INDEX.getRequest().getFullRequestPath()
With these classes:
public interface RequestType {
Request getRequest();
}
public class Request {
private final String requestMapping;
private final String path;
RatesURI(String requestMapping, String path){
this.requestMappint = requestMapping;
this.path = path;
}
public String getRequestMapping(){
return requestMapping;
}
public String getPath(){
return path;
}
public String getFullRequestPath(){
return requestMapping + "/" + path;
}
}
public enum ServiceRequest implements RequestType {
INDEX("index"),
GET_ALL_USERS( "getAllUsers");
private final Request;
ServiceRequest(String path) {
request = new Request("users/", path)
}
public String getRequest{
return request;
}
}
I think what you should be asking yourself is really why you want to use enums for this. First we can review some of the points that make Java enumerated types what they are.
Specifically
A Java enum is a class that extends java.lang.Enum.
Enum constants are static final instances of that class.
There is some special syntax to use them but that is all they boil down to. Because instantiating new Enum instances is disallowed outside of the special syntax (even with reflection, enum types return zero constructors) the following is also ensured to be true:
They can only be instantiated as static final members of the enclosing class.
The instances are therefore explicitly constant.
As a bonus, they are switchable.
What it really boils down to is what it is about the enums that makes them preferable over a simpler OOP design here. One can easily create a simple RequestMapping class:
/* compacted to save space */
public class RequestMapping {
private final String mapping, path;
public RequestMapping(String mapping, String path) {
this.mapping = mapping; this.path = path;
}
public String getMapping() {
return mapping; }
public String getPath() {
return path; }
public String getFullRequestPath() {
return mapping + "/" + path;
}
}
Which can easily be extended to break down the repeated code:
public class UserMapping extends RequestMapping {
public UserMapping(String path) {
super("/users", path);
}
}
/* where ever appropriate for the constants to appear */
public static final RequestMapping INDEX = new UserMapping("index"),
GET_ALL_USERS = new UserMapping("getAllUsers");
But I assume there is something about enums that is attractive to your design, such as the principle that instances of them are highly controlled. Enums cannot be created all willy-nilly like the above class can be. Perhaps it's important that there be no plausible way for spurious instances to be created. Of course anybody can come by and write in an enum with an invalid path but you can be pretty sure nobody will do it "by accident".
Following the Java "static instances of the outer class" enum design, an access modifier structure can be devised that generally abides by the same rule set as Enum. There are, however, two problems which we can't get around easily.
Two Problems
Protected modifier allows package access.
This can easily be surmounted initially by putting the Enum-analog in its own package. The problem becomes what to do when extending. Classes in the same package of the extended class will be able to access constructors again potentially anywhere.
Working with this depends on how stringent you want to be on creating new instances and, conversely, how clear the design ends up. Can't be a whole mess of scopes just so only a few places can do the wrong thing.
Static members are not polymorphic.
Enum surmounts this by not being extendable. Enum types have a static method values that appears "inherited" because the compiler inserts it for you. Being polymorphic, DRY and having some static features means you need instances of the subtype.
Defeating these two issues depends on how stringent you want your design to be and, conversely, how readable and stable you want your implementation to be. Trying to defy OOP principles will get you a design that's hard to break but totally explodes when you call that one method in a way you aren't supposed to (and can't prevent).
First Solution
This is almost identical to the Java enum model but can be extended:
/* 'M' is for 'Mapping' */
public abstract class ReturnMapping<M extends ReturnMapping> {
/* ridiculously long HashMap typing */
private static final HashMap <Class<? extends ReturnMapping>, List<ReturnMapping>>
VALUES = new HashMap<Class<? extends ReturnMapping>, List<ReturnMapping>>();
private final String mapping, path;
protected Mapping(String mapping, String path) {
this.mapping = mapping;
this.path = path;
List vals = VALUES.get(getClass());
if (vals == null) {
vals = new ArrayList<M>(2);
VALUES.put(getClass(), vals);
}
vals.add(this);
}
/* ~~ field getters here, make them final ~~ */
protected static <M extends ReturnMapping> List<M>(Class<M> rm) {
if (rm == ReturnMapping.class) {
throw new IllegalArgumentException(
"ReturnMapping.class is abstract");
}
List<M> vals = (List<M>)VALUES.get(rm);
if (vals == null) {
vals = new ArrayList<M>(2);
VALUES.put(rm, (List)vals);
}
return Collections.unmodifiableList(vals);
}
}
Now extending it:
public final class UserMapping extends ReturnMapping<UserMapping> {
public static final UserMapping INDEX = new UserMapping("index");
public static final UserMapping GET_ALL_USERS = new UserMapping("getAllUsers");
private UserMapping(String path) {
super("/users", path);
}
public static List<UserMapping> values() {
return values(UserMapping.class);
}
}
The huge static HashMap allows almost all of the values work to be done statically in the superclass. Since static members are not properly inherited this is the closest you can get to maintaining a list of values without doing it in the subclass.
Note there are two problems with the Map. The first is that you can call the values with ReturnMapping.class. The map should not contain that key (the class is abstract and the map is only added to in the constructor) so something needs to be done about it. Instead of throwing an exception you could also insert a "dummy" empty list for that key.
The other problem is that you can call values on the superclass before the instances of the subclass are instantiated. The HashMap will return null if this is done before the subclass is accessed. Static problem!
There is one other major problem with this design because the class can be instantiated externally. If it's a nested class, the outer class has private access. You can also extend it and make the constructor public. That leads to design #2.
Second Solution
In this model the constants are an inner class and the outer class is a factory for retrieving new constants.
/* no more generics--the constants are all the same type */
public abstract class ReturnMapping {
/* still need this HashMap if we want to manage our values in the super */
private static final HashMap <Class<? extends ReturnMapping>, List<Value>>
VALUES = new HashMap<Class<? extends ReturnMapping>, List<Value>>();
public ReturnMapping() {
if (!VALUES.containsKey(getClass())) {
VALUES.put(getClass(), new ArrayList<Value>(2));
}
}
public final List<Value> values() {
return Collections.unmodifiableList(VALUES.get(getClass()));
}
protected final Value newValue(String mapping, String path) {
return new Value(getClass(), mapping, path);
}
public final class Value {
private final String mapping, path;
private Value(
Class type,
String mapping,
String path) {
this.mapping = mapping;
this.path = path;
VALUES.get(type).add(this);
}
/* ~~ final class, field getters need not be ~~ */
}
}
Extending it:
public class UserMapping extends ReturnMapping {
public static final Value INDEX, GET_ALL_USERS;
static {
UserMapping factory = new UserMapping();
INDEX = factory.newValue("/users", "index");
GET_ALL_USERS = factory.newValue("/users", "getAllUsers");
}
}
The factory model is nice because it solves two problems:
Instances can only be created from within the extending class.
Anybody can create a new factory but only the class itself can access the newValue method. The constructor for Value is private so new constants can only be created by using this method.
new UserMapping().values() forces the values to be instantiated before returning them.
No more potential errors in this regard. And the ReturnMapping class is empty and instantiating new objects in Java is fast so I wouldn't worry about overhead. You can also easily create a static field for the list or add static methods such as in solution #1 (though this would deflate the design's uniformity).
There are a couple of downsides:
Can't return the subtyped values List.
Now that the constant values are not extended they are all the same class. Can't dip in to generics to return differently-typed Lists.
Can't easily distinguish what subtype a Value is a constant of.
But it's true this could be programmed in. You could add the owning class as a field. Still shaky.
Sum Of It
Bells and whistles can be added to both of these solutions, for example overriding toString so it returns the name of the instance. Java's enum does that for you but one of the first things I personally do is override this behavior so it returns something more meaningful (and formatted).
Both of these designs provide more encapsulation than a regular abstract class and most importantly are far more flexible than Enum. Trying to use Enum for polymorphism is an OOP square peg in a round hole. Less polymorphism is the price to pay for having enumerated types in Java.

Extending enum fields Java

I know that it isn't possible to extend enum in Java, but I am trying to find an elegant solution for the below
I am trying to model enums (or classes) which will contain http end points of various web services across regions, say I have service A and B, each will have 4 region specific end points in US, EU, JP or CN. (This is basically for some seperate debug code that I am writing, in production the end points will be picked from configuration)
I was hoping to do something like this (not compliant java code).
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum ServiceAEndPoint extends IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
I could do this using interfaces where I have a method for each region, but in my opinion the enum way is more expressive, is there any better way I could model this ? What I am looking for is if there is any better way to model the inheritence relation and also having the expressive power of enumerations.
ServiceAEndPoint.NA_END_POINT
vs
serviceAEndPoint.getNAEndPoint()
I'm assuming that you will also want a ServiceBEndPoint enum (and similar). In which case I don't think your model really makes that much sense.
IEndPoint is really an enumeration of the kind of environments/regions where a service might be running. It is not an enumeration of the services themselves. Each individual service (A, B or whatever) will have different addresses for each of the regions.
Therefore I would stick with just the IEndPoint enum, and then in some service-specific code have a lookup map that will give you the address for a given end-point. Something like this:
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public class ServiceABroker {
private static final Map<IEndPoint, String> addressesByEndPoint;
static {
addressesByEndPoint = new EnumMap<>();
addressesByEndPoint.put(NA_END_POINT, "http://A.com/");
addressesByEndPoint.put(EU_END_POINT, "http://A-eu.com/");
addressesByEndPoint.put(JP_END_POINT, "http://A-jp.com/");
addressesByEndPoint.put(CN_END_POINT, "http://A-cn.com/");
}
public String getAddressForEndPoint(IEndPoint ep) {
return addressesByEndPoint.get(ep);
}
}
If these are static final constants, then just put them in an interface. Name the interface something like IServiceAEndPointKeys, where the keys part is a convention.
Here's where I consider enums to be more appropriate and useful:
Example 1: File type. An enum containing jpg, pdf etc.
Example 2: Column definitions. If I have a table with 3 columns, I would write an enum declaring ID, Name, Description (for example), each one having parameters like column header name, column width and column ID.
Im not sure I understand you question, but you can add methods to an enum for example you could do something like the following:
public enum ServiceAEndPoint{
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
private final String url;
private EndPoint(String url){
this.url=url;
}
public String getURL(){
return url;
}
}
Enums cannot be extended in such a manner, mostly because enums cannot be sub-classed or the constraints they must adhere to will not be possible to impose.
Instead leverage interfaces, like so
public interface IEndPoint;
public enum DefaultEndPoints implements IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum DefaultServiceEndPoints implements IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
public void doSomething(IEndPoint endpoint) {
...
}
The reason why one can't subclass in the manner you wish is related to the contract that enums will be both equal via .equals(object) and via ==. If you could subclass, would this make sense?
if ( (DefaultEndPoints)JP_END_POINT == (DefaultServiceEndPoints)JP_END_POINT) {
}
if you say "yes" then I would expect to be able to do this
DefaultEndPoint someEndpoint = DefaultServiceEndPoints.JP_END_POINT;
which would leave a door open for error, as there is no guarantee that a enum entry in one enum declaration is in the other enum declaration.
Could it be different? Perhaps, but it isn't, and changing it would definately introduce a lot of complications that would have to be thoroughly thought out (or it would open avenues to work around Java's strong static-type checking).
You may want to consider something like this:
public abstract class EndpointFactory {
public abstract String getNAEndPoint();
public abstract String getEUEndPoint();
}
public class ServiceAEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://A.com/";
public static final String EU_END_POINT = "http://A-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
public class ServiceBEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://B.com/";
public static final String EU_END_POINT = "http://B-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
Then you can refer to your strings directly like this:
ServiceAEndpointFactory.NA_END_POINT;
Or, you can use the base object if the type of service is not known until execution:
EndpointFactory ef1 = new ServiceAEndpointFactory();
String ep = ef1.getNAEndPoint();
The drawback of this is the redefinition of the get*Endpoint() functions in each sub-class. You could eliminate that by moving the static final variables to be not static in the base class and putting the getter/setter in the base class only one time. However, the drawback of that is you are not able to reference the values without instantiating an object (which essentially emulates what I find valuable with ENUMs).
How does a pattern like this appeal to you? I let the enum implement an interface and implement the interface in a Debug set and a Release set. The release set can then derive the property name from the enum name - which is neat.
public interface HasURL {
public String getURL();
}
public enum DebugEndPoints implements HasURL {
NA,
EU,
JP,
CN;
#Override
public String getURL() {
// Force debug to go to the same one always.
return "http://Debug.com/";
}
}
public enum NormalEndPoints implements HasURL {
NA,
EU,
JP,
CN;
final String url;
NormalEndPoints () {
// Grab the configured property connected to my name.
this.url = getProperty(this.name());
}
#Override
public String getURL() {
return url;
}
}

Categories

Resources