首页 > 解决方案 > 抽象掉 Matrix 库依赖

问题描述

我正在编写一个用于学习的玩具线性代数库,并用于玩具神经网络库。我想使用不同的 Java 线性代数库来测试效率,但我停留在抽象上。

假设我希望我自己的 Matrix 抽象是 add、subtract、multiply、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,因此我需要围绕该库实现这个包装器,在这里我偶然发现了这些方法无法返回我的矩阵的问题,它们必须在实现类时返回矩阵的类型。然而,这打破了抽象。

所以我认为下一步是创建一个 UJMPMatrix 类,它扩展了任何库(在本例中为 UJMP)所需的矩阵类并实现了我的 Matrix 接口,如下所示:

public class UJMPMatrix extends org.ujmp.core.DefaultDenseDoubleMatrix2D 
    implements my.library.Matrix<org.ujmp.core.Matrix, Double> {
....
}

有了这个,我现在已经失去了抽象,因为 defaultdensedoublematrix2d 已经在其中包含所有这些方法,而我只想要在我的界面中提供的那些方法。我该如何进行?

标签: javaoopinheritanceabstraction

解决方案


如果 UJMPMatrix 扩展 DefaultDenseDoubleMatrix2D 则所有公共 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
}

推荐阅读