Java let superclass return 扩展类型 class
Java let superclass return type of extended class
我现在的情况:
我有一个超级class矩阵:
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 class 扩展,它具有一些特定于向量的方法(例如计算向量的长度)。
现在,假设我有一个名为的矢量对象,我想按某个系数缩放它。然后我会调用 vector.scale(1234);
这会产生一个矩阵对象。
但是,我希望结果是矢量对象。我当然可以覆盖 Vector class 中的缩放方法并将 superclass 的结果转换为 Vector class 的对象,但这似乎不是正确的方法去做这个。
任何人都可以给我一些关于如何实现它的指示,以便我可以扩展 Matrix class 并拥有子 classes return 自己类型的对象他们什么时候调用缩放方法?
您可以使 scale
通用。喜欢
public class Matrix<T> {
// ...
public T scale(int scaleFactor) {
// Some code that returns a scaled version of the matrix
}
}
那么你的子 类 可以 extend Matrix<Vector>
。请注意,在 Matrix
中实际实施 scale
会很困难;让它 abstract
像
可能更好
public abstract class Matrix<T> {
// ...
public abstract T scale(int scaleFactor);
}
然后你的子类必须提供一个实现。
您可以做的一件简单的事情就是使方法通用:
public <T extends Matrix> T scale(int scaleFactor) { ... }
使用时需要提供泛型。例如,如果你想 Vector
被 returned,你必须做:
Matrix something = ....
Vector result = something.<Vector>scale(...);
更好的选择是使 scale
方法 abstract
:
public <T extends Matrix> T scale(int scaleFactor);
然后,在 Matrix
的所有子类中,您将被迫使用属于 Matrix
的子类型的 return 类型来实现该方法。
如果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 中被削弱:您现在也可以使用子类型来创建重写方法 "more specific."
这种方法相对于泛型的优势在于它很干净,不需要(隐式)强制转换,并且它精确地限制了类型而没有任何泛型魔法。
[编辑] 现在 Vector
只是一种特殊的 Matrix
(1-column/row 类型),这意味着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;
}
}
如果class是不可变的(很可能应该是),那么你需要使用拷贝构造函数,当然:
public Matrix scale(int scaleFactor) {
Matrix result = new Matrix(this);
result.doScale(scaleFactor);
return result;
}
您有点触及 Java 中泛型类型的限制之一,如果不在子类中重新定义 public Matrix scale(int scaleFactor)
然后重新定义,我认为没有简单的解决方法- 定义 return 类型:public Vector scale(int scaleFactor)
.
我现在的情况: 我有一个超级class矩阵:
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 class 扩展,它具有一些特定于向量的方法(例如计算向量的长度)。
现在,假设我有一个名为的矢量对象,我想按某个系数缩放它。然后我会调用 vector.scale(1234);
这会产生一个矩阵对象。
但是,我希望结果是矢量对象。我当然可以覆盖 Vector class 中的缩放方法并将 superclass 的结果转换为 Vector class 的对象,但这似乎不是正确的方法去做这个。
任何人都可以给我一些关于如何实现它的指示,以便我可以扩展 Matrix class 并拥有子 classes return 自己类型的对象他们什么时候调用缩放方法?
您可以使 scale
通用。喜欢
public class Matrix<T> {
// ...
public T scale(int scaleFactor) {
// Some code that returns a scaled version of the matrix
}
}
那么你的子 类 可以 extend Matrix<Vector>
。请注意,在 Matrix
中实际实施 scale
会很困难;让它 abstract
像
public abstract class Matrix<T> {
// ...
public abstract T scale(int scaleFactor);
}
然后你的子类必须提供一个实现。
您可以做的一件简单的事情就是使方法通用:
public <T extends Matrix> T scale(int scaleFactor) { ... }
使用时需要提供泛型。例如,如果你想 Vector
被 returned,你必须做:
Matrix something = ....
Vector result = something.<Vector>scale(...);
更好的选择是使 scale
方法 abstract
:
public <T extends Matrix> T scale(int scaleFactor);
然后,在 Matrix
的所有子类中,您将被迫使用属于 Matrix
的子类型的 return 类型来实现该方法。
如果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 中被削弱:您现在也可以使用子类型来创建重写方法 "more specific."
这种方法相对于泛型的优势在于它很干净,不需要(隐式)强制转换,并且它精确地限制了类型而没有任何泛型魔法。
[编辑] 现在 Vector
只是一种特殊的 Matrix
(1-column/row 类型),这意味着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;
}
}
如果class是不可变的(很可能应该是),那么你需要使用拷贝构造函数,当然:
public Matrix scale(int scaleFactor) {
Matrix result = new Matrix(this);
result.doScale(scaleFactor);
return result;
}
您有点触及 Java 中泛型类型的限制之一,如果不在子类中重新定义 public Matrix scale(int scaleFactor)
然后重新定义,我认为没有简单的解决方法- 定义 return 类型:public Vector scale(int scaleFactor)
.