[英]One class for math vectors of arbitrary dimension
我想写一个数学矢量类(保持实数)。 我认为Vector操作几乎与矢量的维度无关,所以不是像Vector2D
, Vector3D
, Vector4D
那样编写类......我只想写一个Vector
类。
现在的问题是我无法将2D矢量与4D矢量相乘,所以我想到了一个场dimension
。 但现在我必须检查每次操作,所以我问自己是否可以做得更好。 这是仿制药在我脑海中浮现的。 但是我又要做一些像Vector<? extends Dimension>
Vector<? extends Dimension>
,其中Dimension
只是Dimension.One
, Dimension.Two
等的基类,这意味着,我必须为我想要使用vectos的每个维度编写一个Dimension
类。
所以我的问题:
有没有办法为任意维度的向量编写一个类而无需在运行时检查维度?
如果我正确理解你的问题,那么答案就是你不能同时拥有这两个问题。 您可以使用类型系统来确保正确的维度,然后最终会出现大量的显式类型(泛型对您没有帮助),或者您每次执行操作时都使用状态来跟踪维度并执行动态检查。 由于向量的“维度”是它所包含的元素数量,因此将在底层数据结构中以某种方式表示。 例如,如果使用列表将值存储在向量中,则列表将知道它包含的元素数量。 因此,进行简单的运行时检查很便宜,并且您可以在尺寸不匹配时抛出异常。 与基于类型的解决方案相比,该解决方案更灵活,更易于编程。
您可以在Dimension
类中嵌入一个执行检查的方法,如果向量不兼容,则抛出Runtime Exception
。 然后让Dimension
每个方法都调用此方法。 现在, 使用 Dimension
类的代码不会乱码。
你可以编写一个带有一些有趣泛型的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维。 每个实现都解决了这个问题。
为了弄清楚为什么我想使用泛型(它的作用就是为什么我把它作为答案发布):
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的答案非常相似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.