Question

I want to write a class for mathematical Vectors (holding real numbers). I figured that Vector operations are pretty much the same regardeless of the dimension of the vector, so instead of writing classes like Vector2D, Vector3D, Vector4D, ... I just want to write a Vector class.

Now the problem is that I can't multiply a 2D vector with a 4D one, so I thought about a field dimension. But now I had to check it for every operation so I asked myself if I can do better than that. This is were generics came to my mind. But then again I have to do something like Vector<? extends Dimension>, where Dimension is simply a base class of Dimension.One, Dimension.Two and so on, which means, I have to write a Dimension class for every dimension I want to use vectos in.

So my question:

Is there a way of writing one class for vectors of arbitrary dimension without having to check the dimension at runtime?

Was it helpful?

Solution

If I understand your question correctly, then the answer is that you can't have both. Either you use the type system to ensure correct dimensionality, and then you end up with a proliferation of explicit types (generics won't help you), or you use state to track the dimensions and perform dynamic checks every time you perform an operation. Since the "dimension" of a vector is how many elements it holds, this will be represented somehow in the underlying data structure. For example if you use a list to store the values in the vector, the list knows how many elements it contains. So doing a simple runtime check is cheap and you can throw an exception when dimensions don't match. That solution is much more flexible and easy to program with than a type based solution.

OTHER TIPS

You can embed in the Dimension class a method that performs the check and throws a Runtime Exception if the vectors are incompatible. Then have every method in Dimension invoke this method. Now the code that uses the Dimension class won't be littered with checks.

You could write a Vector class with some interesting generics

public static class Vector<V extends Vector<V>>{
    protected double[] components;
    public final int dimensions;
    private Class<V> klass;

    protected Vector(int d, Class<V> klass) {
        this.klass = klass;
        this.components = new double[d];
    }

    public double get(int x) { return components[x] }
    protected void set(int x, double d) { components[x] = d }

    public V clone() {
        try {
            V c = klass.newInstance();
            c.components = this.components.clone();
            return c;
        }
        catch(InstantiationException e1) {}
        catch(IllegalAccessException e2) {}
        return null;
    }

    public V add(V that) {
        V sum = this.clone();
        for(int i = 0; i < dimensions; i++)
            sum.components[i] += that.components[i];
        return sum;
    }

}

Then derive each case:

   

public static class Vector2D extends Vector<Vector2D>{
    public Vector2D() { 
        super(2, Vector2D.class);
    }
    public Vector2D(double x, double y) { 
        this();
        set(0, x);
        set(1, y);
    }
}
public static class Vector3D extends Vector<Vector3D>{
    public Vector3D() { 
        super(3, Vector3D.class);
    }
    public Vector3D(double x, double y, double z) { 
        this();
        set(0, x);
        set(1, y);
        set(2, z);
    }
}
public static class Vector4D extends Vector<Vector4D>{
    public Vector4D() { 
        super(4, Vector4D.class);
    }
    public Vector4D(double w, double x, double y, double z) { 
        this();
        set(0, w);
        set(1, x);
        set(2, y);
        set(3, z);
    }
}

After all, there are special cases - for instance, a cross product only exists in 3 and 7 dimensions. Having an implementation for each solves this.

To make clear why I wanted to use generics (it works which is why I'm posting it as an answer):

Dimension.java:

public class Dimension {
    class ONE extends Dimension {}
    class TWO extends Dimension {}
    class THREE extends Dimension {}
    // [...]
}

Vector.java:

public class Vector<D extends Dimension> {
    private double[] elements;

    public Vector(double _elmts) {
        elements = _elmts;
    }

    public void add(Vector<D> v) { /*...*/ }
    public void subtract(Vector<D> v) { /*...*/ }
}

But as mentioned in my Question, I have to create several classes, which is what I wanted to prevent in the first place. Also it's rather ugly. And there's no way to make sure elements has the right dimension other than trusting the user.

I guess it's pretty similar to Eric's answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top