I am trying to write an abstract class that is a blueprint for the types of data and behaviors that all of its children should have. However, the return types of these enforced methods will depend on the child class itself.
I have been informed in the comments to one of my many closed questions that what I am doing here is overloading my parents methods instead of overriding them. I understand this is because I changed the method signature, and @Override
requires that the signature be identical, but the implementation can be different.
public abstract class BaseMatrix {
protected int[] shape;
protected int nrows;
protected int ncols;
public BaseMatrix(int rows, int cols){
this.nrows = rows;
this.ncols = cols;
this.shape = new int[]{nrows, ncols};
}
// ** here is the method I want to implement/override **
public abstract BaseMatrix mmul(BaseMatrix other);
I initially tried to use generics to overcome the problem but discovered I don't understand them well enough to implement a solution that way. So instead I took the advice found in two similary questions: https://stackoverflow.com/a/20638886/3696204 and Proper use of generics in abstract java class?
public class ND4JDenseMatrix extends BaseMatrix{
private INDArray data;
public ND4JDenseMatrix(int rows, int cols) {
super(rows, cols);
this.data = Nd4j.zeros(this.shape);
}
// ** Here is my attempt at implementing the abstract method. **
@Override
public ND4JDenseMatrix mmul(ND4JDenseMatrix other) {
INDArray product = this.data.mmul(other.data);
ND4JDenseMatrix result = new ND4JDenseMatrix(this.nrows, this.ncols);
result.setData(product);
return this;
}
}
This results in a warning at the @Override
:
Method does not override method from its superclass
However, if I use the identical method signature in the child class:
public class ND4JDenseMatrix extends BaseMatrix{
public BaseMatrix mmul(BaseMatrix other) { ...implementation...}
}
Then Someone could pass ANY child of the BaseMatrix
class mmul()
, which would almost certainly break.
Given that I know that I am overloading and not overriding, how can I achieve the functionality described in the first section of my question that enforces the type being passed to the child class methods?
Assuming the inheritance at subject is a technical one and not to be used with polymorphism in mind (since the return value is not polymorphic of the BaseMatrix
type), it is possible using generics.
public abstract class BaseMatrix<T extends BaseMatrix<T>> {
protected int[] shape;
protected int nrows;
protected int ncols;
public BaseMatrix(int rows, int cols){
this.nrows = rows;
this.ncols = cols;
this.shape = new int[]{nrows, ncols};
}
public abstract T mmul(T other);
}
public class ND4JDenseMatrix extends BaseMatrix<ND4JDenseMatrix> {
private INDArray data;
public ND4JDenseMatrix(int rows, int cols) {
super(rows, cols);
this.data = Nd4j.zeros(this.shape);
}
@Override
public ND4JDenseMatrix mmul(ND4JDenseMatrix other) {
INDArray product = this.data.mmul(other.data);
ND4JDenseMatrix result = new ND4JDenseMatrix(this.nrows, this.ncols);
result.setData(product);
return this;
}
}