为了账号安全,请及时绑定邮箱和手机立即绑定

如何实例化泛型类型?

如何实例化泛型类型?

交互式爱情 2023-06-08 20:55:06
我正在为 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. 我需要性能,所以那不理想。我知道我可以使用反射来解决问题,但这些方法对性能至关重要,所以我必须尽可能简单。我还考虑过更改参数中的向量,这样我就不必实例化一个新的向量,但这是一个非常糟糕的主意,因为它会导致奇怪的行为。任何帮助表示赞赏。
查看完整描述

2 回答

?
当年话下

TA贡献1890条经验 获得超9个赞

最简单的方法似乎是在Vector类上有一个实例方法:


Vector make(double[] values) {

  return new Vector(values);

}

然后在每个子类中覆盖它,使用协变返回类型:


class Vector3 extends Vector {

  //...


  @Override Vector3 make(double[] values) {

    return new Vector3(values);

  }


  //...

}

然后你可以在你的 multiply 方法中调用它。


return vector.make(values);

但老实说,我不会尝试将向量的长度编码为类型。当你需要一个包含 57032 个元素的向量时会发生什么?您肯定不想为此创建一个特定的类,对吗?如果您有两个Vector具有相同数量元素的不同子类,会发生什么情况:它们是否兼容(例如相加)?


更自然地处理向量的语言(例如 MATLAB)不会将其构建到类型中;问问自己是否真的需要这里。


查看完整回答
反对 回复 2023-06-08
?
LEATH

TA贡献1936条经验 获得超6个赞

如果它对性能至关重要,您实际上可能会考虑让 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);

        }

    }

}


查看完整回答
反对 回复 2023-06-08
  • 2 回答
  • 0 关注
  • 168 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信