views:

59

answers:

2

This probably has a very simple solution, but I can't seem to figure it out...
We have a bunch of classes of the form xQuantity, e.g. DistanceQuantity, AreaQuantity, etc., which extend a class DimensionQuantity. Now you can add or subtract DistanceQuantity's or AreaQuantity's, etc., but you can't mix them. All of the subclasses have methods like add(), subtract(), ge(), etc., so it would be nice to put the shared logic into DimensionQuantity, but I keep running into cast problems.

So far the best I have come up with is to generate an object, and then cast it in the subclass's method, but it would be nice to get rid of the subclass add() (and the other similar methods) altogether! Here is the code (with some stuff left out):

In DistanceQuantity:

public DistanceQuantity add(DistanceQuantity d1) {
 Object o = new DistanceQuantity(scalar + d1.scalar, REF_UNIT);     
 return (DistanceQuantity) o;
    }

In DimensionQuantity:

@SuppressWarnings({"rawtypes", "unchecked"})
  public Object add(DimensionQuantity d1)  {

 Class c1 = this.getClass();
 Class c2 = d1.getClass();
 if (c1 != c2)
    throw new RuntimeException();
 double d = scalar + d1.scalar;
 Constructor c = null;  
 c = c1.getConstructor(Double.TYPE, AbstractUnit.class);
 Object o = null;  
 o = c.newInstance(d, REF_UNIT);  
 return o;
    }

Can someone (or someones) suggest a better way?!

+1  A: 

Use a class declaration like this: class Dimension<T extends Dimension<T>> {...}. This allows you to specify a subclass like class AreaDimension extends Dimension<AreaDimension> {...}.

Note that I think you're doing this the wrong way - if you are going to have Distance, Area, Volume classes then simply have additionally to the value, the exponent or dimensionality - simple Distance has dimensionality 1, Area has 2, Volume has 3. This allows you to do multiplication and division properly.

If you are going to have more than a single unit, use an enumeration for the various units, and an array for the dimensions of each.

Tassos Bassoukos
Thanks, everyone! Actually, I was trying for too much generality, which would have cost me the static type checking that I wanted. I think I have a pretty good compromise now. So please ignore the above code - but your comments were helpful!
Paul Morrison
A: 

This problem has pretty much gone away - I have found a very different solution, so I believe this answer will close this question off! However, it has prompted a related question about how one would get a "macro" or "template" facility into the Java language, but this is probably not the forum to pose it... If anyone can suggest where I should ask it (or has an answer), I would love to hear about it. Thanks again to all of you.

Paul Morrison