有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java通过结构化设计模式重构冗余代码

下面是一段代码,用于检查变量赋值和模拟某些ANTLR语法的in行为的语句表达式之间的类型兼容性

// LoopAnalyzer.java

@Override
public void exitForInLoop(ForInLoopContext ctx) {
    final String rightHandSideType = this.determineExpressionReturnType(ctx.statementExpression());
    this.verifyTypeCompatibility(ctx.start, ctx.solType().getText(), rightHandSideType);
}

此代码将读取并确定由determineExpressionReturnType方法表示的语句表达式返回类型,然后通过将变量声明类型与右侧数组的基元形式进行比较来验证类型兼容性。更具体地说,给出in语句的一个示例片段:

for (string item in items) {
    // do something with the item
}

在该示例中,item的类型应该与items的基本形式匹配,并且items本身应该是一个数组。否则,将引发一条不兼容错误消息,从而妨碍for in语句在对象items上枚举。类似于此类行为的类型兼容性检查逻辑在verifyTypeCompatibility方法中进行编码,如下所示:

// LoopAnalyzer.java

private void verifyTypeCompatibility(Token token, String leftHandSideType, String rightHandSideType) {
    if (rightHandSideType == null || leftHandSideType == null) {
        return;
    }

    if (!TypeUtils.isArrayType(leftHandSideType, rightHandSideType)) {
        this.addError(token, String.format("Types are not compatible, cannot check containment of %s in %s.", leftHandSideType, rightHandSideType));
    }
}

代码看起来不错,直到我意识到for in语句的类型检查和变量声明的类型检查非常相似,只有很小的区别。与in语句不同,变量声明语句只需要语句表达式类型等于分配给变量名的类型

为简单起见,检查变量声明语句的代码片段如下所示:

// ExpressionStatementAnalyzer.java

@Override
public void exitVariableDeclarationStatement(VariableDeclarationStatementContext ctx) {
    final String rightHandSideType = this.determineExpressionReturnType(ctx.statementExpression());
    this.verifyTypeCompatibility(ctx.start, ctx.solType().getText(), rightHandSideType);
}

private void verifyTypeCompatibility(Token token, String leftHandSideType, String rightHandSideType) {
    if (rightHandSideType == null || leftHandSideType == null) {
        return;
    }

    if (!TypeUtils.areCompatible(leftHandSideType, rightHandSideType)) {
        this.addError(token, String.format("Cannot assign a %s value to a %s variable.", rightHandSideType, leftHandSideType));
    }
}

有了这些微小的差异,我们如何提取相似的组件以便在这两个类中重用

目前,我只能想到结构设计模式,其中我们将determineExpressionReturnTypeverifyTypeCompatibility保留在ExpressionStatementAnalyzer类中,并让LoopAnalyzer扩展该类,以便它可以覆盖这两种方法当前可用的实现。但是,这种方法不太可能是解决方案,因为分析循环语句与分析语句表达式无关(即,它们假定不相互继承)。于是我问了这个问题


共 (1) 个答案

  1. # 1 楼答案

    LoopAnalyzer肯定不是ExpressionStatementAnalyzer。 您可以添加一个抽象分析器,它公开verifyTypeCompatibility方法:

     public abstract class AbstractAnalyzer {
          protected void verifyTypeCompatibility(Token token, String leftHandSideType, String rightHandSideType)
          {
               if (rightHandSideType == null || leftHandSideType == null) {
                   return;
               }
    
               if (!IsTypeCompatible(leftHandSide, rightHandSide) {
                   this.addError(token, String.format("Cannot assign a %s value to a %s variable.", rightHandSideType, leftHandSideType));
               }
          }
    
          protected abstract bool IsTypeCompatible(string leftHandSide, string rightHandSide);
     }
    

    然后,您可以让LoopAnalyzer和ExpressionStatementAnalyzer扩展AbstractAnalyzer并实现IsTypeCompatible方法

    如果可以将exitVariableDeclarationStatement和ExitForInLopStatement的名称更改为exitStatement,则还可以将此方法的实现移动到AbstractAnalyzer