Нам было дано задание создать структуру объекта для оценки выражений (например, «1 + 2» или «true & false»).Предоставляется синтаксический анализатор, а также фабричный интерфейс для создания объектов выражений.
Мы используем обобщенные значения для различных выражений: Expression<Integer>
возвращает целое число, Expression<Boolean>
возвращает логическое значение и т. Д.
Проблема, с которой мы сталкиваемся, состоит в том, что предоставленный интерфейс использует необработанный тип Expression
, например:
public Expression createSumExpression(Expression left, Expression right);
Выражение суммы определяется только в том случае, если операнды имеют тип Expression<Integer>
илиExpression<Double>
.Как мы можем это проверить?Из-за стирания типа информация о типе недоступна во время выполнения, и это просто приводит к ClassCastException
, если оно неверно.
Я могу изменить все, кроме функций createSumExpression
и createAndExpression
.
Это упрощенный фрагмент кода, демонстрирующий проблему.Это работает, но выглядит не очень хорошо и выдает несколько предупреждений.
Main.java
public class Main {
public static void main(String[] args) {
Expression<?> left1 = new BasicExpression<>(42);
Expression<?> right1 = new BasicExpression<>(3);
Expression<?> sum = createSumExpression(left1, right1);
System.out.printf("%d + %d = %d%n",left1.getValue(), right1.getValue(), sum.getValue());
Expression<?> left2 = new BasicExpression<>(true);
Expression<?> right2 = new BasicExpression<>(false);
Expression<?> and = createAndExpression(left2, right2);
System.out.printf("%b & %b = %b%n",left2.getValue(), right2.getValue(), and.getValue());
}
private static Expression createSumExpression(Expression left, Expression right) { // Raw types because of given interface
return new BinaryExpression<Integer,Expression<Integer>,Expression<Integer>>(left, right) {
@Override
protected Integer operation(Expression<Integer> left, Expression<Integer> right) {
return left.getValue() + right.getValue();
}
};
}
private static Expression createAndExpression(Expression left, Expression right) { // Raw types because of given interface
return new BinaryExpression<Boolean,Expression<Boolean>,Expression<Boolean>>(left, right) {
@Override
protected Boolean operation(Expression<Boolean> left, Expression<Boolean> right) {
return left.getValue() & right.getValue();
}
};
}
}
Expression.java
abstract public class Expression<V> {
public abstract V getValue();
}
BasicExpression.Java
public class BasicExpression<V> extends Expression<V> {
public BasicExpression(V value) {
this.value = value;
}
@Override
public V getValue() {
return value;
}
private V value;
}
BinaryExpression.java
abstract public class BinaryExpression<V, L, R> extends Expression<V> {
public BinaryExpression (L l, R r) {
this.left = l;
this.right = r;
}
@Override
public V getValue() {
return operation(left, right);
}
abstract protected V operation(L left, R right);
private L left;
private R right;
}
Предоставляемый интерфейс:
/**
* @param <E>
* Your class for representing an expression.
*/
public interface IExpressionFactory<E> {
public E createSumExpression(E left, E right) throws ModelException;
public E createAndExpression(E left, E right) throws ModelException;
// ...
}