抽象掉 Matrix 库依赖
Abstracting away Matrix library dependency
我正在编写一个玩具线性代数库,用于学习和在玩具神经网络库中使用。我想使用不同的 Java 线性代数库来测试效率,但我停留在抽象上。
假设我希望我自己的 Matrix 抽象是加法、减法、乘法、hadamardMultiply、map 和 mapElements,如下所示:
// I would prefer for this to force the implementing classes to be immutable...
// M is the type of implementing matrix
public interface Matrix<M,T extends Number> {
M add(M in); // return this matrix + in
// overload add(T)
// default subtract = add (-1 * T)
M multiply(M in); // return this matrix X in
// overload multiply(T)
// default divide = multiply(T^-1)
M hadamardMultiply(M in); // return this matrix hadamard in
T map(Function<M,T> map); // f: M -> T
M mapElements(UnaryOperator<T> map); // f: T -> T
}
我所说的不可变的意思是我的 API 应该看起来像
Matrix<vendor.matrix.VendorMatrix, Double> multiple = myMatrix.multiply(someOtherMatrix);
// or
Matrix<vendor.matrix.VendorMatrix, Double> add = myMatrix.add(5);
// and
Matrix<vendor.matrix.VendorMatrix, Double> mapped = myMatrix.map(e -> e / Math.PI);
这不应该改变 myMatrix。
现在我以前使用过 UJMP,所以我需要围绕那个库实现这个包装器,在这里我偶然发现了这些方法不能 return 我的矩阵的问题,在实施 classes 时,他们必须 return 矩阵的类型。然而,这打破了抽象。
所以我认为下一步是制作一个 UJMPMatrix class,它扩展了任何库(在本例中为 UJMP)所需的矩阵 class 并像这样实现我的 Matrix 接口:
public class UJMPMatrix extends org.ujmp.core.DefaultDenseDoubleMatrix2D
implements my.library.Matrix<org.ujmp.core.Matrix, Double> {
....
}
有了这个,我现在已经失去了抽象,因为 defaultdensedoublematrix2d 已经有了所有这些方法,而我只想要我的界面中提供的方法。我该如何进行?
如果 UJMPMatrix 扩展了 DefaultDenseDoubleMatrix2D,那么所有 public UJMP 方法都会被公开。您需要使用委托模式。
关于泛型类型,您还需要对其进行更改,以便它可以接受其他 UJMPMatrix 作为方法参数。
public class UJMPMatrix implements my.library.Matrix<UJMPMatrix, Double> {
private org.ujmp.core.DefaultDenseDoubleMatrix2D delegate;
// Implement the methods of your interface by using the delegate
}
我正在编写一个玩具线性代数库,用于学习和在玩具神经网络库中使用。我想使用不同的 Java 线性代数库来测试效率,但我停留在抽象上。
假设我希望我自己的 Matrix 抽象是加法、减法、乘法、hadamardMultiply、map 和 mapElements,如下所示:
// I would prefer for this to force the implementing classes to be immutable...
// M is the type of implementing matrix
public interface Matrix<M,T extends Number> {
M add(M in); // return this matrix + in
// overload add(T)
// default subtract = add (-1 * T)
M multiply(M in); // return this matrix X in
// overload multiply(T)
// default divide = multiply(T^-1)
M hadamardMultiply(M in); // return this matrix hadamard in
T map(Function<M,T> map); // f: M -> T
M mapElements(UnaryOperator<T> map); // f: T -> T
}
我所说的不可变的意思是我的 API 应该看起来像
Matrix<vendor.matrix.VendorMatrix, Double> multiple = myMatrix.multiply(someOtherMatrix);
// or
Matrix<vendor.matrix.VendorMatrix, Double> add = myMatrix.add(5);
// and
Matrix<vendor.matrix.VendorMatrix, Double> mapped = myMatrix.map(e -> e / Math.PI);
这不应该改变 myMatrix。
现在我以前使用过 UJMP,所以我需要围绕那个库实现这个包装器,在这里我偶然发现了这些方法不能 return 我的矩阵的问题,在实施 classes 时,他们必须 return 矩阵的类型。然而,这打破了抽象。
所以我认为下一步是制作一个 UJMPMatrix class,它扩展了任何库(在本例中为 UJMP)所需的矩阵 class 并像这样实现我的 Matrix 接口:
public class UJMPMatrix extends org.ujmp.core.DefaultDenseDoubleMatrix2D
implements my.library.Matrix<org.ujmp.core.Matrix, Double> {
....
}
有了这个,我现在已经失去了抽象,因为 defaultdensedoublematrix2d 已经有了所有这些方法,而我只想要我的界面中提供的方法。我该如何进行?
如果 UJMPMatrix 扩展了 DefaultDenseDoubleMatrix2D,那么所有 public UJMP 方法都会被公开。您需要使用委托模式。
关于泛型类型,您还需要对其进行更改,以便它可以接受其他 UJMPMatrix 作为方法参数。
public class UJMPMatrix implements my.library.Matrix<UJMPMatrix, Double> {
private org.ujmp.core.DefaultDenseDoubleMatrix2D delegate;
// Implement the methods of your interface by using the delegate
}