繁体   English   中英

如何实例化泛型类型?

[英]How do I instantiate a generic type?

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

所以我所做的是一个Vector类,它将成为所有向量的母类。 我可以让Vector类没有子节点,但我更喜欢这些子类,因为我可以在它们上添加特定的东西,比如Vector3中的euler角度操作,我也想使用Vector4作为Quaternion的母类。 无论如何,这是我简化的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因为我需要返回的向量与发送的向量相同。

如果我做新的Vector2(4,2).multiply(42),我需要得到一个Vector2而不是Vector。 我也可以在Vector2中使用Multily方法调用Vector乘法,然后复制Vector2中的值但是1.它很糟糕,2。这意味着在子矢量之间有很多复制粘贴,3。我需要性能,所以那不太理想。

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

我还想过改变参数中的向量,所以我不必实例化一个新的,但这是一个非常糟糕的主意,因为它可能会导致奇怪的行为。

任何帮助表示赞赏。

最简单的方法似乎是在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)不会将其构建到类型中; 问问自己这里是否真的需要它。

如果它是性能关键的,你可能会考虑使用乘法方法来改变向量的状态而不是创建一个新的。 在我看来,只要它是一种确定性和记录在案的行为,它就不奇怪了。

但是,对于不可变的向量类,您需要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);
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM