【发布时间】:2018-05-16 15:13:35
【问题描述】:
我们的任务是创建一个对象结构来评估表达式(例如“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;
// ...
}
【问题讨论】:
-
你能修改
Expression本身吗? -
@JornVernee 是的,我可以修改
Expression。 -
IMO,这是接口签名的概念问题。如果
createSumExpression只接受Integer和Double,则方法的签名应该是public Expression createSumExpression(Expression<? extends Number> left, Expression<? extends Number> right);以防止出现任何异常。而且由于不能修改,所以没有"clear"解决方案。