3

数学的ベクトル (実数を保持) のクラスを作成したいと考えています。ベクトルの操作はベクトルの次元に関係なくほとんど同じであると考えたので、 、 、 、 ... のようなクラスを書く代わりに、クラスVector2DVector3D書きVector4DたいだけですVector

問題は、2D ベクトルと 4D ベクトルを乗算できないことです。そのため、フィールドについて考えましたdimension。しかし、今ではすべての操作でそれをチェックしなければならなかったので、それよりもうまくやれるかどうか自問自答しました. これは、ジェネリックが頭に浮かんだことです。しかしVector<? extends Dimension>、ここでDimensionは単純に の基本クラスであるDimension.Oneなどのようなことをしなければなりません。つまり、ベクトルを使用するすべての次元に対してクラスをDimension.Two作成する必要があります。Dimension

だから私の質問:

実行時に次元をチェックすることなく、任意の次元のベクトルに対して 1 つのクラスを作成する方法はありますか?

4

4 に答える 4

2

私があなたの質問を正しく理解しているなら、答えはあなたが両方を持つことはできないということです。型システムを使用して正しい次元を確保してから、明示的な型が急増するか(ジェネリックスは役に立ちません)、状態を使用して次元を追跡し、操作を実行するたびに動的チェックを実行します。ベクトルの「次元」はそれが保持する要素の数であるため、これは基礎となるデータ構造で何らかの形で表されます。たとえば、リストを使用して値をベクトルに格納する場合、リストには含まれる要素の数がわかります。したがって、単純なランタイムチェックを実行するのは安価であり、ディメンションが一致しない場合は例外をスローできます。このソリューションは、タイプベースのソリューションよりもはるかに柔軟でプログラミングが簡単です。

于 2012-06-02T12:58:05.763 に答える
2

チェックを実行し、ベクトルに互換性がない場合はDimensionaをスローするメソッドをクラスに埋め込むことができます。Runtime Exception次に、すべてのメソッドでDimensionこのメソッドを呼び出します。これで、クラスを使用するコードDimensionにチェックが散らばることはなくなります。

于 2012-06-02T12:59:34.033 に答える
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そして、ユーザーを信頼する以外に、正しい次元を持っていることを確認する方法はありません。

エリックの答えとかなり似ていると思います。

于 2012-06-02T15:34:12.273 に答える
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 に答える