2 回答
TA贡献1876条经验 获得超5个赞
你可以使用 lambda:
private Object visitBinaryOperatorNode(BinaryOpNode node, BiFunction<T, T> op) {
Object lhs = node.getLeftHandSide().accept(this);
Object rhs = node.getRightHandSide().accept(this);
if (lhs instanceof Long && rhs instanceof Long) {
return op.apply((long) lhs, (long) rhs);
}
throw new TypeError("Can not take " + node.getOpName() + "of " + lhs.getClass() + " and " + rhs.getClass() + ".");
}
但是,由于您的某些运算符支持多种类型,因此您需要另一层抽象:
@RequiredArgsConstructor// Lombok, otherwise write the boilerplate yourself
public class BinaryOperator<T, T> {
@NonNull private final BiFunction<T, T> op;
@NonNull private final Class<T> clazz;
public boolean isApplicable(Object left, Object right) {
return clazz.isInstance(left) && clazz.isInstance(right);
}
public T apply(Object left, Object right) {
return op.apply(clazz.cast(left), clazz.cast(right));
}
}
您现在可以传递一组有效的二元运算符并测试它们是否适用,如果适用,则应用它们。
private static final List<BinaryOperator<?, ?>> VALID_ADD_OPERATORS = Arrays.asList(
new BinaryOperator<>((x, y) -> x + y, Double.class),
new BinaryOperator<>((x, y) -> x + y, Long.class),
new BinaryOperator<>((x, y) -> x + y, String.class)
);
private static final List<BinaryOperator<?, ?>> VALID_MULTIPLY_OPERATORS = Arrays.asList(
new BinaryOperator<>((x, y) -> x * y, Double.class),
new BinaryOperator<>((x, y) -> x * y, Long.class)
);
@Override
public Object visitAddNode(AddNode addNode) {
return visitBinaryOperatorNode(addNode, VALID_ADD_OPERATORS );
}
@Override
public Object visitMultiplyNode(MultiplyNode multiplyNode) {
return visitBinaryOperatorNode(multiplyNode, VALID_MULTIPLY_OPERATORS );
}
private Object visitBinaryOperatorNode(BinaryOpNode node, List<BinaryOperator<?, ?>> validOperators) {
Object lhs = node.getLeftHandSide().accept(this);
Object rhs = node.getRightHandSide().accept(this);
for (BinaryOperator<?, ?> op : validOperators) {
if (op.isApplicable(lhs, rhs)) return op.apply(lhs, rhs);
}
throw new TypeError("Can not take " + node.getOpName() + "of " + lhs.getClass() + " and " + rhs.getClass() + ".");
}
TA贡献1796条经验 获得超4个赞
您可以将这些检查提取到单独的对象中,并在需要时重用它。
例如,通过为要处理转换的每种类型定义一个枚举值。
例如
public enum ConvertType {
DOUBLE {
Object apply(Object lhs, Object rhs) {
if (lhs instanceof Double && rhs instanceof Double) {
return (double) lhs + (double) rhs;
}
return null;
}
},
LONG {
Object apply(Object lhs, Object rhs) {
if (lhs instanceof Long && rhs instanceof Long) {
return (long) lhs + (long) rhs;
}
return null;
}
},
STRING {
Object apply(Object lhs, Object rhs) {
if (lhs instanceof String && rhs instanceof String) {
return "" + lhs + lhs;
}
return null;
}
};
public static Object apply(Object a, Object b, ConvertType... convertTypes) {
for (ConvertType convertType : convertTypes) {
Object result = convertType.apply(a, b);
if (result != null) {
return result;
}
}
throw new TypeError("Can not take modulus of " + a.getClass() + " and " + b.getClass() + ".");
}
}
转换的入口点是静态方法:
public static Object apply(Object a, Object b, ConvertType... convertTypes)
ConvertType多亏了var-args.
例如 :
@Override
public Object visitMultiplyNode(MultiplyNode multiplyNode) {
Object lhs = multiplyNode.getLeftHandSide().accept(this);
Object rhs = multiplyNode.getRightHandSide().accept(this);
return ConvertType.apply(lhs , rhs, ConvertType.DOUBLE, ConvertType.LONG);
}
或者 :
@Override
public Object visitAddNode(AddNode addNode) {
Object lhs = addNode.getLeftHandSide().accept(this);
Object rhs = addNode.getRightHandSide().accept(this);
return ConvertType.apply(lhs , rhs, ConvertType.DOUBLE, ConvertType.LONG, ConvertType.STRING);
}
添加回答
举报