Search code examples
javaoopinheritanceabstraction

Abstracting away Matrix library dependency


I'm writing a toy linear algebra library for learning and to be used in a toy neural network library. I would like to use different Java linear algebra libraries to test efficiency, but I'm stuck at the abstraction.

Suppose I would like my own Matrix abstraction to be add, subtract, multiply, hadamardMultiply, map, and mapElements like so:

// 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
}

What I mean by immutable is that my API should look like

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);

which should not alter the myMatrix.

Now I've previously used UJMP, and so I need to implement this wrapper around that library, and here is where I stumbled upon the issue that these methods cannot return my Matrix, they have to return the type of the matrices in implementing classes. However, this breaks the abstraction.

So I thought that the next step would be to make a UJMPMatrix class, which extends whichever library's (in this case UJMP) desired matrix class and implements my Matrix interface like so:

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

With this, I have now lost the abstraction, as the defaultdensedoublematrix2d already has all of these methods in them, when I only want the ones provided in my interface. How do I proceed?


Solution

  • If UJMPMatrix extends DefaultDenseDoubleMatrix2D then all the public UJMP methods are exposed. You need to use the delegate pattern.

    Regarding the generics typing you will also need change it so it can accept other UJMPMatrix as method arguments.

    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
    }