Abstraindo a dependência da biblioteca Matrix
Estou escrevendo uma biblioteca de álgebra linear de brinquedo para aprendizado e para ser usada em uma biblioteca de rede neural de brinquedo. Gostaria de usar diferentes bibliotecas de álgebra linear Java para testar a eficiência, mas estou preso na abstração.
Suponha que eu gostaria que minha própria abstração Matrix fosse adicionar, subtrair, multiplicar, hadamardMultiply, map e mapElements assim:
// 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
}
O que quero dizer com imutável é que minha API deve ser semelhante a
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);
que não deve alterar o myMatrix.
Agora já usei o UJMP anteriormente e, portanto, preciso implementar esse wrapper em torno dessa biblioteca, e foi aqui que me deparei com o problema de que esses métodos não podem retornar minha Matrix, eles devem retornar o tipo das matrizes nas classes de implementação. No entanto, isso quebra a abstração.
Então pensei que a próxima etapa seria fazer uma classe UJMPMatrix, que estende qualquer classe de matriz desejada da biblioteca (neste caso UJMP) e implementa minha interface Matrix assim:
public class UJMPMatrix extends org.ujmp.core.DefaultDenseDoubleMatrix2D
implements my.library.Matrix<org.ujmp.core.Matrix, Double> {
....
}
Com isso, agora perdi a abstração, pois o defaultdensedoublematrix2d já contém todos esses métodos, quando desejo apenas os fornecidos em minha interface. Como eu prossigo?
Respostas
Se UJMPMatrix estende DefaultDenseDoubleMatrix2D, todos os métodos públicos UJMP são expostos. Você precisa usar o padrão de delegado.
Em relação à tipagem dos genéricos, você também precisará alterá-la para que possa aceitar outros UJMPMatrix como argumentos do método.
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
}