Cześć. Próbuje zrobić aplikację w stylu bardzo uproszczonego MatLaba tzn. Będzie jakaś konsola gdzie będzie można definiować różne zmienne o różnych typach np. macierz, ułamek, liczba zespolona, a następnie odwołać się do niej w innej zmiennej. Coś w tym stylu:
A = matrix(4, 5) //(typ zmiennej A : macierz)
B = complex(5, 2) * A.determinant //(typ zmiennej B : liczba zespolona)
C = A * B //(typ zmiennej C : macierz)
Jako że dla każdego obiektu - ułamka, macierzy, liczby zespolonej, można wykonać podstawowe działania arytmetyczne (dzielenie przez macierz będzie traktowanie jako mnożenie przez jej odwrotność podniesioną do odpowiedniej potęgi), zacząłem od stworzenia interfejsu MathObject:
public interface MathObject {
MathObject add(MathObject object);
MathObject subtract(MathObject object);
MathObject multiply(MathObject object);
MathObject divide(MathObject object);
}
oraz interfejsów dla poszczególnych typów zmiennych (ułamek, macierz, liczba zespolona):
public interface IFraction extends MathObject {
//metody dla IFraction
}
public interface IComplex extends MathObject {
//metody dla IFraction
}
public interface IMatrix extends MathObject {
//metody dla IFraction
}
Następnie interfejs funkcyjny Function zwracający obiekt typu MathObject (tutaj będzie zapisana funkcja np. = matrix(4, 5), = A * B)
@FunctionalInterface
public interface Function<T extends MathObject> {
T getValue();
}
I w końcu klasa zmiennej która przechowuje określoną funkcję:
public interface IVariable {
Function getFunction();
IVariable add(IVariable variable);
IVariable subtract(IVariable variable);
IVariable multiply(IVariable variable);
IVariable divide(IVariable variable);
}
public class Variable implements IVariable {
private Function function;
public Variable(Function function) {
this.function = function;
}
@Override
public IVariable add(IVariable variable) {
return new Variable(() -> function.getValue().add(variable.getFunction().getValue()));
}
@Override
public IVariable subtract(IVariable variable) {
return new Variable(() -> function.getValue().subtract(variable.getFunction().getValue()));
}
@Override
public IVariable multiply(IVariable variable) {
return new Variable(() -> function.getValue().multiply(variable.getFunction().getValue()));
}
@Override
public IVariable divide(IVariable variable) {
return new Variable(() -> function.getValue().divide(variable.getFunction().getValue()));
}
@Override
public Function getFunction() {
return function;
}
}
Problem pojawił się podczas implementacji typów, ponieważ każdy z nich w zależności klasy implementującej oraz od typu argumentu object musi zwrócić nowy obiekt określonego typu. Dla przykładu klasa Complex:
public class Complex implements IComplex {
@Override
public MathObject add(MathObject object) {
if(object instanceof IComplex) {
return [NOWY OBIEKT TYPU IComplex]
} else if(object instanceof IFraction) {
return [NOWY OBIEKT TYPU IFraction]
} else if(object instanceof IMatrix) {
return [NOWY OBIEKT TYPU IMatrix]
}
}
//reszta dziedziczonych metod
}
Jak na razie jedynie powyższe rozwiązanie przyszło mi do głowy, ale z tego co przeczytałem używanie instanceof nie jest najlepszą opcją. Czy da się w jakiś sposób uzyskać powyższy efekt nie używając instanceof ? Będę wdzięczny za każdą wskazówkę :).