我想写一个数学向量类(保持实数)。我认为Vector操作几乎与vector的维度无关,所以不是像Vector2D
,Vector3D
,Vector4D
那样编写类,我只是想写一个Vector
课程。
现在的问题是我不能将2D矢量与4D矢量相乘,所以我想到了一个字段dimension
。但现在我必须检查每次操作,所以我问自己是否可以做得更好。这是仿制药在我脑海中浮现的。但是我必须再做Vector<? extends Dimension>
之类的事情,其中Dimension
只是Dimension.One
的基类,Dimension.Two
等等,这意味着,我必须写一个我想要使用vectos的每个维度的Dimension
类。
所以我的问题:
有没有办法为任意维度的向量编写一个类而不必在运行时检查维度?
答案 0 :(得分:2)
如果我理解你的问题,那么答案是你不能同时拥有这两个问题。您可以使用类型系统来确保正确的维度,然后最终会出现大量的显式类型(泛型对您没有帮助),或者您每次执行操作时都使用状态来跟踪维度并执行动态检查。 由于向量的“维度”是它所包含的元素数量,因此将在底层数据结构中以某种方式表示。例如,如果使用列表将值存储在向量中,则列表将知道它包含的元素数量。因此,进行简单的运行时检查很便宜,并且您可以在尺寸不匹配时抛出异常。与基于类型的解决方案相比,该解决方案更灵活,更易于编程。
答案 1 :(得分:2)
如果向量不兼容,您可以在Dimension
类中嵌入执行检查的方法并抛出Runtime Exception
。然后让Dimension
中的每个方法都调用此方法。现在,使用 Dimension
类的代码将不会出现问题。
答案 2 :(得分: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维。每个实现都解决了这个问题。
答案 3 :(得分:0)
要明确我为什么要使用泛型(这就是为什么我将其作为答案发布的原因):
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) { /*...*/ }
}
但正如我的问题所提到的,我必须创建几个类,这是我想要首先防止的。它也相当难看。除了信任用户之外,没有办法确保elements
具有正确的维度。
我想这与Eric的答案非常相似。