3

我想为数学向量(保存实数)编写一个类。我认为无论向量的维度如何,向量操作都几乎相同,所以我不想写像Vector2D, Vector3D, Vector4D, ... 这样的类,我只想写一个Vector类。

现在的问题是我不能将 2D 矢量与 4D 相乘,所以我想到了 field dimension。但现在我必须检查每一次手术,所以我问自己是否可以做得更好。这是我想到的泛型。但话又说回来,我必须做类似的事情Vector<? extends Dimension>,其中Dimension​​只是 的一个基类Dimension.OneDimension.Two等等,这意味着我必须为Dimension我想在其中使用 vectos 的每个维度编写一个类。

所以我的问题:

有没有一种方法可以为任意维度的向量编写一个类,而无需在运行时检查维度?

4

4 回答 4

2

如果我正确理解您的问题,那么答案是您不能两者兼得。要么使用类型系统来确保正确的维度,然后最终导致显式类型的激增(泛型对您没有帮助),要么使用状态来跟踪维度并在每次执行操作时执行动态检查。由于向量的“维度”是它包含多少个元素,这将在底层数据结构中以某种方式表示。例如,如果您使用列表将值存储在向量中,则列表知道它包含多少元素。所以做一个简单的运行时检查很便宜,当尺寸不匹配时你可以抛出异常。该解决方案比基于类型的解决方案更灵活且易于编程。

于 2012-06-02T12:58:05.763 回答
2

您可以在类中嵌入Dimension一个方法,该方法执行检查并Runtime Exception在向量不兼容时抛出 a。然后让每个方法都Dimension调用这个方法。现在,使用该类的代码Dimension不会被检查乱七八糟。

于 2012-06-02T12:59:34.033 回答
0

你可以用一些有趣的泛型编写一个 Vector 类

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;
    }

}

然后推导出每个案例:

   

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);
    }
}

毕竟,有一些特殊情况——例如,叉积只存在于 3 维和 7 维中。每个都有一个实现可以解决这个问题。

于 2012-06-02T12:57:59.350 回答
0

为了弄清楚我为什么要使用泛型(它有效,这就是我将其发布为答案的原因):

维度.java:

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

向量.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) { /*...*/ }
}

但正如我的问题中提到的,我必须创建几个类,这是我首先要防止的。而且还比较丑。elements除了信任用户之外,没有其他方法可以确保具有正确的维度。

我想这与埃里克的回答非常相似。

于 2012-06-02T15:34:12.273 回答