簡體   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