Seite 1 von 1

Ex09: Splitting the visitor?

Verfasst: 31. Jan 2014 15:29
von mmi1991
We don't understand the benefits of having a startVisit and an endVisist method since usually we would write something like:
def visit(p : ClassX){
//do some stuff at the beginning
//then call the accept methods of the other stuff within ClassX which should be visited then
p.y.accept(this)
//then do the things at the end of the visit
}
the splitting of this method would result in startVisit with the whole stuff until p.y.accept and the endVisit method with the stuff which needs to be done at the end of the visit.
But these two methods must be called from within an accept method so that it is still a visitor pattern. Since usually within accept nothing else is done the splitting doesn't add any additional functionality.

Re: Ex09: Splitting the visitor?

Verfasst: 1. Feb 2014 06:44
von imaier
That depends on where you decide to put the traversal code. The solution on the sheet is merely a hint what you could do (when you put it into the accept methods exclusively). You are open to do it differently, as long as it sticks to one of the common visitor variations.

Michael posted a link to the Javac visitor, which uses only visit methods and will therefore most likely do the traversal on its own. Here is how the visitor in the Java compiler of Eclipse looks like:

http://help.eclipse.org/indigo/index.js ... sitor.html

If you look at its source, you will find that its default implementation does not do any traversal. Therefore (and because visitor implementations have to do some non-trivial things), the visitor needs multiple methods per node, which are called at different times during tree traversal.

If you have time, you can experiment with different implementations and figure the advantages and disadvantages of each approach.

Cheers,
Ingo

Re: Ex09: Splitting the visitor?

Verfasst: 1. Feb 2014 10:57
von mmi1991
imaier hat geschrieben:That depends on where you decide to put the traversal code. The solution on the sheet is merely a hint what you could do (when you put it into the accept methods exclusively).
Thanks for the link ;). We thought that if we put the traversal code within the accept-method it would not be a visitor any more, since we would "force" the visitor to visit some methods. E.g. antlr4 can generate a visitor interface and something it calls listener, which is basically a "forced" visitor.

Thanks again. We will investigate a bit in this. :D

Re: Ex09: Splitting the visitor?

Verfasst: 3. Feb 2014 18:25
von L4_
mmi1991 hat geschrieben:We don't understand the benefits of having a startVisit and an endVisist method since usually we would write something like:
def visit(p : ClassX){
//do some stuff at the beginning
//then call the accept methods of the other stuff within ClassX which should be visited then
p.y.accept(this)
//then do the things at the end of the visit
}
Question to assistant/lecturer:

This kind of implementation might be needed, if we need to traverse elements recursively, right?
(analagous to the slides on page 28)

My decorator pattern is implemented in a way, that e.g. if I am calling ".price" from a decorated object, the result will be the accumulated price.
Thus when printing I do not need to traverse my Pizza/Topping-elements recursively with the visitor.
Therefore, can I just quit on the "endVisit" method or what should/could actually happen in "endVisit" so that printing gets more "easier"?

Kind regards

Re: Ex09: Splitting the visitor?

Verfasst: 4. Feb 2014 09:25
von imaier
No, that implementation is not *needed*. As I said earlier, you have to decide where to put your traversal code, either in the accept methods, i.e., the tree structure, or in the visit methods, i.e., the visitor. Generally you should decide for one and not mix both. And yes, both of these forms count as the Visitor Pattern. Even the Gamma/GoF book, which in places does no mention design alternatives, discuss the two possibilities:
Who is responsible for traversing the object structure? A visitor must visit each element of the object structure. The question is, how does it get there? We can put responsibility for traversal in any of three places: in the object structure, in the visitor, or in a separate iterator object (see Iterator (201)).
Often the object structure is responsible for iteration. A collection will simply iterate over its elements, calling the Accept operation on each. A composite will commonly traverse itself by having each Accept operation traverse the element's children and call Accept on each of them recursively.
Another solution is to use an iterator to visit the elements. [...]
You could even put the traversal algorithm in the visitor, although you'll end up duplicating the traversal code in each ConcreteVisitor for each aggregate ConcreteElement. The main reason to put the traversal strategy in the visitor is to implement a particularly complex traversal, one that depends on the results of the operations on the object structure. We'll give an example of such a case in the Sample Code.
They also give a third option using iterators. We won't discuss this approach in the course, I believe. I don't think it's very common, even though you can sometimes traverse parts of your structure with an iterator.

Cheers,
Ingo