我想编写一个抽象类'Expression',它接受整数或布尔表达式,并通过诸如'Add','Divide'作为整数和'And','Or'作为布尔表达式的子类对它们进行求值。最后,归结为编写实现其自己的validate()方法的子类。我在一本书中找到了一个实现,但它仅适用于double值。在这里:
abstract class Expr {
abstract double eval();
}
abstract class BinOp extends Expr {
Expr left;
Expr right;
BinOp(Expr l, Expr r) {
}
}
class Const extends Expr {
private double value;
Const( double val ) {
this.value = val;
}
double eval () {
return this.value;
}//eval
}
现在,对于BinOp类,我可以编写一个类'Add'对其进行扩展,调用它的构造函数,并使用2个Const对象的乘积实现eval(),这些对象本身是eval()并简单地返回它们实例化的值用。
如果我想使用Expr来做这项工作,而Expr并不严格将其计算为double,而是int或boolean?我已经阅读了泛型,但似乎无法正确设计Expr这样的类来编译我的代码。这是我的尝试:
public abstract class Expression<T> {
abstract T evaluate();
}
public class Const<T> extends Expression{
private T n;
public Const(T x) { n = x; }
public Const<Integer> integerConst(Integer n) {
return new Const<>(n);
}
public Const<Boolean> booleanConstConst(Boolean n) {
return new Const<>(n);
}
public T evaluate() {
return n;
}
}
现在,我不希望任何人为我做功课,所以我只是问我的方法的错误在哪里,是否有人可以指出我正确的方向。谢谢。
答案 0 :(得分:1)
以下是一些建议:
首先,您不应该使用原始类型,因此Const<T>
应该扩展Expression<T>
。
现在,您的integerConst
和booleanConstConst
方法看起来像工厂方法,因此应该是static
。
也就是说,我不确定在Const
类中包含这些工厂方法是否是一个好主意,因为如果您愿意,它将迫使您更改Const
类型支持第三种表达式类型(除了Boolean
和Integer
之外)。相反,您可能要考虑子类Const
:
public class IntegerConst extends Const<Integer> {
public IntegerConst(Integer n) {
super(n);
}
}
public class BooleanConst extends Const<Boolean> {
public BooleanConst(Boolean b) {
super(b);
}
}
希望您可以从这里继续。
答案 1 :(得分:0)
我认为您应该将所有逻辑隐藏在Expression
后面,并且所有类型特定的逻辑都应放在单独的类中。
要隐藏具体的实现,您应该为每个具体的实现使用参数化的Expression
类和工厂方法:
public interface Expression<T> {
T evaluate();
static BooleanExpression with(boolean val) {
return new BooleanExpression(val);
}
static DoubleExpression with(double val) {
return new DoubleExpression(val);
}
}
使用必需的运算符实现“布尔”值:
public final class BooleanExpression implements Expression<Boolean> {
private final boolean left;
public BooleanExpression(boolean left) {
this.left = left;
}
public BooleanExpression and(boolean right) {
return new BooleanExpression(left && right);
}
public BooleanExpression or(boolean right) {
return new BooleanExpression(left || right);
}
@Override
public Boolean evaluate() {
return left;
}
}
使用必需的运算符对integer
值的实现(我使用double
,因为您应该实现divide
):
public final class DoubleExpression implements Expression<Double> {
private final double left;
public DoubleExpression(double left) {
this.left = left;
}
public DoubleExpression add(double right) {
return new DoubleExpression(left + right);
}
public DoubleExpression divide(double right) {
return new DoubleExpression(left / right);
}
@Override
public Double evaluate() {
return left;
}
}
客户端代码向您显示所有具体的实现均已隐藏,并且每个表达式只有可接受的运算符:
boolean res1 = Expression.with(false).and(true).or(true).evaluate(); // true
double res2 = Expression.with(0.5).add(2.5).divide(2).evaluate(); // 1.5