views:

88

answers:

2

I have a class hierarchy representing different language constructs:

Expression <- NumericLiteral
              UnaryExpression
              BinaryExpression
              IndexingExpression
              IteratedExpression
                   ...

The objects of these classes form complex tree hierarchies on which I have to perform various structural checks, e.g. if the node is an IteratedExpression then its first child should be an IndexingExpression. If the check only involves one level I can use the Visitor pattern, but in more complex cases as in the example below I am using instanceof.

void visit(IteratedExpression node) {
    if (!(node.getChild(0) instanceof IndexingExpression)) {
        // report error
    }
}

Is it a proper use of instanceof or I have a flaw in my design? What are the alternatives?

Since there were some alternatives suggested I would like to emphasize the first part of the question:

Is it a proper use of instanceof or I have a flaw in my design?

+1  A: 

add an abstract method to Expression and implement it in its children.
so each class will have its own checks.

Itay
This is called Template Method pattern, and it's standard approach to instanceof problem resolving. However, if you need some more complex logics, you will have to use more complex Structural Patterns. This actually depends on specifics of your design.
Kel
@Itay: As with the Visitor pattern this works only for one level and I am already not using instanceof in this case.
vitaut
+2  A: 

Like this:

class Visitor {
  boolean indexingExpected;
  void startIteratedExpression() {
    indexingExpected = true;
  }
  void doIndexing() {
    indexingExpected = false;
  }
  void someOtherVisit() {
    if (indexingExpected) {
      throw IllegalStateException();
    }
  }
}
clas IteratedExpression {
  private List<Expression> children;
  public void visit(Visitor visitor) {
    visitor.startIteratedExpression();
    for(Expression child : childrenExpression) {
      child.visit(visitor);
    }
    visitor.endIteratedExpression();
  }
}
class IndexingExpression extends Expression {
  public void visit(Visitor visit) {
    visitor.doIndexing();
  }
}

If you want use Visitor it doesn't matter how many levels you have in your tree.

ycnix
IIUC you are suggesting to introduce some kind of a check state into the visitor. That could be a nice solution to my problem. Thanks.
vitaut
Yes, visitor can be a kind of builder, with state. And nodes are responsible for visitor state transitions.
ycnix