У меня есть несколько операндов разных типов, и я хочу определить, как
эти операнды могут действовать друг на друга. Это похоже на общий
проблема, но я не могу найти хороший подход для ее реализации.
Скажем для начала, что у меня есть скаляры (то есть числа), матрица и множества
матрицы или скаляров, и что я хочу определить операцию плюс на них:
scalar1.plus (scalar2) возвращает скаляр, равный scalar1 + scalar2,
matrix.plus (scalar1) или scalar.plus (matrix) оба возвращают матрицу
где 'scalar1' каждый элемент был добавлен к каждому элементу
матрица,
matrixSet.plus (matrix1) возвращает набор, в котором каждая матрица была
добавлено в матрицу1
И так далее ... Обратите внимание, что некоторые операции могут вызывать исключения, такие как
добавление матрицы разных размеров или добавление наборов, которые не имеют
такое же количество элементов.
Мои цели следующие:
1 - повторно использовать как можно больше кода (важно, потому что у меня будет много
больше операций и типов данных),
2 - делать как можно больше проверок во время компиляции
3 - упростить добавление новых типов данных или операций в будущем (для
Например, я могу захотеть добавить векторный тип данных позже)
Сначала я думал, что определю интерфейс операнда, который мой
скаляр, матрица и набор этих элементов будут реализованы, и которые
будет включать такие методы, как:
public Operand plus(Operand op);
Это позволило бы определить операцию плюс снизу вверх,
начиная с самого простого элемента (скаляра):
public Operand plus(Operand operand) {
if (Scalar.class.equals(operand.getClass())) {
return new Scalar(this.value + ((Scalar) operand).getValue());
} else {
// assume the other operand will define the addition for me
// since add is commutative
return operand.plus(this);
}
}
А потом для матрицы:
public Operand plus(Operand operand) {
if (Scalar.class.equals(operand.getClass())) {
// return a matrix where we add scalar value to all matrix elements
} else if (Matrix.class.equals(operand.getClass())) {
// return a matrix where we perform a scalar addition between each element
} else {
// assume the other operand will define the addition for me
// since add is commutative
return operand.plus(this);
}
}
Идея в том, что всякий раз, когда я представляю новый класс, реализующий
Тип операнда (скажем, вектор), мне нужно будет только определить плюс
операция между этим новым операндом и всеми другими существующими
операнды. То есть Я бы не стал переписывать метод плюс
Классы скаляров и матриц.
Этот подход соответствует целям 1 и 3, но не 2: все операции возвращаются
Операнды объектов, и заставляет меня делать много кастинга и классов
проверка во время выполнения, что не кажется хорошей практикой.
Есть ли лучший способ решить мою проблему?