我正在用Java创建一个Matrix
类,用于线性代数程序。现在它持有双打,但我想抽象它。
我创建了一个名为MatrixElement
的接口,它将包含add
、multiply
、divide
,以及执行这些矩阵运算所需的任何其他算术方法。
下面是Matrix
类的一个片段:
public class Matrix<T extends MatrixElement> {
private ArrayList<ArrayList<T>> rows;
public Matrix(int numRows, int numCols) {
if (numRows <= 0) {
throw new IllegalArgumentException("Matrix must have at least one row.");
}
if (numCols <= 0) {
throw new IllegalArgumentException("Matrix must have at least one column.");
}
this.rows = new ArrayList<ArrayList<T>>();
for (int r = 0; r < numRows; r++) {
ArrayList<T> row = new ArrayList<T>();
for (int c = 0; c < numCols; c++) {
row.add(new T());
}
this.rows.add(row);
}
}
/* lots of methods omitted */
public static Matrix sum(Matrix a, Matrix b) {
if (a.numRows() != b.numRows() || a.numCols() != b.numCols()) {
throw new IllegalArgumentException("Matrices must be the same size.");
}
Matrix sum = new Matrix(a.numRows(), b.numCols());
for (int r = 1; r <= b.numRows(); r++) {
for (int c = 1; c <= b.numCols(); c++) {
sum.setEntry(r, c, a.getEntry(r, c).add(b.getEntry(r, c)));
}
}
return sum;
}
public Matrix add(Matrix matrix) {
return Matrix.sum(this, matrix);
}
}
以下是在MatrixElement
中声明方法的方式
public interface MatrixElement {
public MatrixElement add(MatrixElement e);
}
最后,下面是我创建的一个实现此接口的示例类:
public class Fraction implements MatrixElement {
private BigInteger numerator;
private BigInteger denominator;
public Fraction(int num, int denom) {
numerator = BigInteger.valueOf(num);
denominator = BigInteger.valueOf(denom);
}
@Override
public Fraction add(MatrixElement e) {
Fraction f;
try {
f = (Fraction) e;
} catch (ClassCastException cce) {
throw new IllegalMatrixOperationException("Cannot add " + this.getClass().toString() + " and " + e.getClass().toString());
}
/* addition code omitted */
return this;
}
}
这里的主要思想是这样的:
Matrix
对象可以保存实现接口的任何一个类的实例MatrixElement
MatrixElement
包含矩阵操作所需的算术方法,例如add
- 踢球者:实现
MatrixElement
的类只能在同一类的其他实例上使用其方法。例如,Fraction
只能添加到其他Fraction
实例中。两个类可以实现MatrixElement
,但它们不一定能够相互添加。
我由另一位程序员运行了这个设计,并被告知像这样的铸造是一种不好的做法。如果是这样,正确的方法是什么?如何使用接口对具有类似功能的类进行"分组",以便在参数化中使用,但随后限制所述接口的哪些子级可以在子级方法中使用?
在上面的帖子中,对泛型有两个要求。
要求 1:可以添加到同一类型的其他元素的元素
您希望对某些数据类型强加协定,以便可以将这些类型的实例添加到相同类型的其他实例中,并且只能添加到同一类型。目的是支持以下类型的操作:
int + int = int
long + long = long
real fraction + real fraction = real fraction
complex number + complex number = complex number
该合同可以表示如下:
public interface MatrixElement<T> {
T add(T e);
}
用简单的语言来说,这个协定说MatrixElement
是一种类型,其实例可以添加到相同类型的其他实例中,以产生相同类型的另一个实例,这是必需的。
要求2:元素的二维矩阵,所有相同类型的元素都可以添加到相同类型和相同维度的元素的其他二维矩阵中
该合同可以表示为:
public class Matrix<T extends MatrixElement<T>> {
public Matrix<T> add (Matrix<T> another) { ... }
}
这个契约说一个Matrix
由类型MatrixElement
的元素组成,使得所有元素都是同一类型的。Matrix
也允许用另一个Matrix
加法,前提是两者都有相同类型的元素。结果作为具有相同类型元素的第三个Matrix
返回。
Github上提供了一个示例。