I am trying to define a class (or a set of classes implementing the same interface) that will behave like a freely typed object (like JavaScript). They can store any data, and operations with them depend on the base type.
It works for me differently, but no one seems perfect. These test versions only allow strings and integers, and a single operation is added. Adding integers results in a sum of integers, adding strings combines the strings and adding an integer to a string converts the integer to a string and combines it with a string. The final version will have more types (doubles, arrays, objects similar to JavaScript, where new properties can be added dynamically) and more operations.
Method 1:
public interface DynObject1 { @Override public String toString(); public DynObject1 add(DynObject1 d); public DynObject1 addTo(DynInteger1 d); public DynObject1 addTo(DynString1 d); } public class DynInteger1 implements DynObject1 { private int value; public DynInteger1(int v) { value = v; } @Override public String toString() { return Integer.toString(value); } public DynObject1 add(DynObject1 d) { return d.addTo(this); } public DynObject1 addTo(DynInteger1 d) { return new DynInteger1(d.value + value); } public DynObject1 addTo(DynString1 d) { return new DynString1(d.toString()+Integer.toString(value)); } }
... and similar for DynString1
Path 2: public interface DynObject2 {@Override public String toString (); public DynObject2 add (DynObject2 d); }
public class DynInteger2 implements DynObject2 { private int value; public DynInteger2(int v) { value = v; } @Override public String toString() { return Integer.toString(value); } public DynObject2 add(DynObject2 d) { Class c = d.getClass(); if(c==DynInteger2.class) { return new DynInteger2(value + ((DynInteger2)d).value); } else { return new DynString2(toString() + d.toString()); } } }
... and similar for DynString2
Method 3:
public class DynObject3 { private enum ObjectType { Integer, String }; Object value; ObjectType type; public DynObject3(Integer v) { value = v; type = ObjectType.Integer; } public DynObject3(String v) { value = v; type = ObjectType.String; } @Override public String toString() { return value.toString(); } public DynObject3 add(DynObject3 d) { if(type==ObjectType.Integer && d.type==ObjectType.Integer) { return new DynObject3(Integer.valueOf(((Integer)value).intValue()+((Integer)value).intValue())); } else { return new DynObject3(value.toString()+d.value.toString()); } } }
With if-else logic, I could use value.getClass () == Integer.class instead of saving the type, but with a lot of types I would change this to use the switch statement, and Java doesn't allow the use of the Class switch.
Anyway ... My question is the best way to do something like this?