我目前的情况: 我有一个超类矩阵:
public class Matrix {
private final float[] values;
private final int numberOfRows;
private final int numberOfColumns;
public Matrix(int rows, int columns, float... values) {
this.values = new float[numberOfRows * numberOfColumns];
this.numberOfRows = numberOfRows;
this.numberOfColumns = numberOfColumns;
System.arraycopy(values, 0, this.values, 0, values.length);
}
public Matrix scale(int scaleFactor) {
//Some code that returns a scaled version of the matrix
}
}
由Vector类扩展,该类具有一些特定于矢量的方法(例如,计算矢量的长度)。
现在,假设我有一个名为的矢量对象,我想通过某种因素来缩放它。然后我会调用vector.scale(1234);
,这会产生一个矩阵对象。
但是,我希望结果是一个矢量对象。我当然可以覆盖Vector类中的scale方法,并将超类的结果强制转换为Vector类的对象,但这似乎不是正确的方法。
有没有人能给我一些关于如何实现这一点的指示,以便我可以扩展Matrix类并让子类的对象在调用scale方法时返回自己的对象类型?
答案 0 :(得分:2)
如果Vector extends Matrix
,您可以:
public class Matrix {
public Matrix scale(int scaleFactor) {
... return Matrix ...
}
}
public class Vector extends Matrix {
...
@Override
public Vector scale(int scaleFactor) { // <-- return sub type here!
... return Vector ...
}
}
重写方法必须具有相同类型的规则在Java 5中被削弱了:您现在也可以使用子类型来使覆盖方法“更具体”。
这种方法优于泛型的优点在于它是干净的,不需要(隐式)强制转换,并且它完全限制了类型而没有任何泛型魔法。
[编辑] 现在Vector
只是一种特殊的Matrix
(1列/行类型),这意味着scale()
中的代码是一样的。
不幸的是,这不起作用:
public class Vector extends Matrix {
...
@Override
public Vector scale(int scaleFactor) { // <-- return sub type here!
return (Vector) super.scale(scaleFactor);
}
}
因为您无法将Matrix
个实例转换为Vector
。解决方案是将比例代码移动到辅助方法中:
public class Matrix {
protected void doScale(int scaleFactor) {
... original scale() code here...
}
public Matrix scale(int scaleFactor) {
doScale(scaleFactor);
return this;
}
}
public class Vector extends Matrix {
...
@Override
public Vector scale(int scaleFactor) {
doScale(scaleFactor);
return this;
}
}
如果类是不可变的(它可能应该是),那么你需要使用复制构造函数,当然:
public Matrix scale(int scaleFactor) {
Matrix result = new Matrix(this);
result.doScale(scaleFactor);
return result;
}
答案 1 :(得分:1)
您可以scale
通用。像
public class Matrix<T> {
// ...
public T scale(int scaleFactor) {
// Some code that returns a scaled version of the matrix
}
}
那么您的子类可以extend Matrix<Vector>
。请注意,在scale
中实际实现Matrix
很困难;最好让它abstract
像
public abstract class Matrix<T> {
// ...
public abstract T scale(int scaleFactor);
}
然后您的子类必须提供实现。
答案 2 :(得分:1)
您可以做的一件容易的事情就是使方法具有通用性:
public <T extends Matrix> T scale(int scaleFactor) { ... }
使用它时,您需要提供通用类型。例如,如果您想要返回Vector
,则必须执行以下操作:
Matrix something = ....
Vector result = something.<Vector>scale(...);
更好的选择是制作scale
方法abstract
:
public <T extends Matrix> T scale(int scaleFactor);
然后,在Matrix
的所有子类中,您将被迫使用返回类型实现该方法,该类型是Matrix
的子类型。
答案 3 :(得分:0)
你在Java中遇到了泛型类型的限制之一,如果没有在子类中重新定义public Matrix scale(int scaleFactor)
然后重新定义返回类型,我就看不到简单的方法: public Vector scale(int scaleFactor)
。