猿问

如何实例化泛型类型?

我正在为 Java 项目制作一些数学课程。我有一个 Vector3 类,但我还需要 Vector4 和 Vector2,但显然我不想复制粘贴我的代码 3 次。


所以我所做的是一个 Vector 类,它将成为所有向量的母类。我可以只使用没有子类的 Vector 类,但我更喜欢使用这些子类,因为我可以在它们上面添加特定的东西,比如 Vector3 中的欧拉角操作,而且我想使用 Vector4 作为四元数的母类。无论如何,这是我简化的 Vector 类:


public class Vector {


    public double[] values;


    public Vector(double[] values) {

        this.values = values;

    }


    public int getLength() { 

        return values.length; 

    }


    public static <T extends Vector> T multiply(T vector, double k) {


        double[] values = new double[vector.getLength()];

        for(int i = 0; i < values.length; i++)

            values[i] = k* vector.values[i];

        return new T(values);

    }

}

public class Vector3 extends Vector {

    public Vector3(double[] values) {

        super(values);

    }

}

问题是编译器不会让我实例化一个 T:“类型参数 T 不能直接实例化”。但是我需要这个 T 因为我需要返回的向量与发送的向量类型相同。


如果我执行 new Vector2(4,2).multiply(42),我需要得到一个 Vector2 而不是一个 Vector。我还可以在 Vector2 中创建一个乘法方法,该方法调用 Vector multiply,然后将值复制到 Vector2 中,但是 1. 这很糟糕,2. 这意味着子向量之间有很多复制粘贴,3. 我需要性能,所以那不理想。


我知道我可以使用反射来解决问题,但这些方法对性能至关重要,所以我必须尽可能简单。


我还考虑过更改参数中的向量,这样我就不必实例化一个新的向量,但这是一个非常糟糕的主意,因为它会导致奇怪的行为。


任何帮助表示赞赏。


交互式爱情
浏览 169回答 2
2回答

当年话下

最简单的方法似乎是在Vector类上有一个实例方法:Vector make(double[] values) {&nbsp; return new Vector(values);}然后在每个子类中覆盖它,使用协变返回类型:class Vector3 extends Vector {&nbsp; //...&nbsp; @Override Vector3 make(double[] values) {&nbsp; &nbsp; return new Vector3(values);&nbsp; }&nbsp; //...}然后你可以在你的 multiply 方法中调用它。return vector.make(values);但老实说,我不会尝试将向量的长度编码为类型。当你需要一个包含 57032 个元素的向量时会发生什么?您肯定不想为此创建一个特定的类,对吗?如果您有两个Vector具有相同数量元素的不同子类,会发生什么情况:它们是否兼容(例如相加)?更自然地处理向量的语言(例如 MATLAB)不会将其构建到类型中;问问自己是否真的需要这里。

LEATH

如果它对性能至关重要,您实际上可能会考虑让 multiply 方法改变向量的状态,而不是创建一个新的。在我看来,这并不奇怪,只要它是确定性的和记录在案的行为即可。但是,对于不可变向量类,您需要clone向量。public class Vector implements Cloneable {    // not a good idea to make it public, if you don't want any changes here    private double[] values;    public static <T extends Vector> T multiply(T vector, double k) {        Vector temp = vector.clone();        for(int i = 0; i < temp.values.length; i++)            temp.values[i] = k * temp.values[i];        // the clone method guarantees that 'temp' is of type T,        // but since it is not generic, the compiler cannot check it        @SuppressWarnings("unchecked")         T result = (T)temp;        return result;    }    protected Vector clone() {        try {            Vector vector = (Vector)super.clone();            vector.values = Arrays.copyOf(values, values.length);            return vector;        } catch (final CloneNotSupportedException exc) {            // this is a weird design choice of `Object.clone()`, too,            // but back then, we did not have annotations or anything equivalent            throw new AssertionError("we forgot to implement java.lang.Cloneable", exc);        }    }}
随时随地看视频慕课网APP

相关分类

Java
我要回答