html5-img
1 / 27

Visitor

Visitor. Visitor Intent. Intent : Represent an operation to be performed on the elements of an object structure in a class separate from the elements themselves. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

jessie
Download Presentation

Visitor

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Visitor

  2. Visitor Intent • Intent: Represent an operation to be performed on the elements of an object structure in a class separate from the elements themselves. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

  3. Visitor Possible Structure

  4. When to use a Visitor • Whenever you have a number of items on which you have to perform a number of actions • When you ‘decouple’ the actions from the items. • Examples: • the parse tree (ProgramNode) uses a visitor for the compilation (emitting code on CodeStream) • GraphicsContext is a visitor for VisualComponents, Geometrics, and some other ones (CharacterArray, ...) • Rendering documents

  5. Applying the Visitor • So all our problems are solved, no? • Well... • how to define it • when to use a visitor • control over item traversal • choosing the granularity of visitor methods • implementation tricks

  6. Visitor Toy Example • Language to deal with arithmetic expressions. • It supports one kind of number, and has +, *, (, ) • We want to evaluate expressions, and print them.

  7. Example • Evaluating • 1 + 1 • gives = 2 • 1 + (3 * 2) • gives 7 • Printing • +1*32

  8. Visitor Toy Example: ParseTree

  9. Expressions creation • 1 • ENumber value: 1 • (3 * 2) • Times left: (ENumber value: 3) right: (ENumber value: 2) • 1 + (3 * 2) • Plus • left: (ENumber value: 1) • right: (Times left: (ENumber value: 3) right: (ENumber value: 2)) • Of course in Smalltalk we can just extend Number so no • need of ENumber value:.....

  10. Implementing the Actions • Two solutions: • add methods for evaluating, printing, ... on Expression and its subclasses • create a Visitor, add the visit methods on Expression and its subclasses, and implement visitors for evaluation, printing, ...

  11. Visitor Toy Example Solution 1

  12. Expressions creation • (ENumber value: 1) evaluate • > 1 • (Times left: (ENumber value: 3) right: (ENumber value: 2)) evaluate • > 6 • (Plus left: (ENumber value: 1) right: (Times left: (ENumber value: 3) right: (ENumber value: 2))) evaluate • > 7

  13. Limits of the approach • printing is not easy may need specific instance variables • adding it directly on Expression clutters Expression • may need to add instance variables that are not part of the tree • behavior of the printer are mixed with expressions

  14. Visitor Toy Example 2

  15. Expressions creation • Evaluator evaluate: (ENumber value: 1) • > 1 • Evaluator evaluate: (Times left: (ENumber value: 3) right: (ENumber value: 2)) • > 6 • Evaluator evaluate: (Plus left: (ENumber value: 1) right: (Times left: (ENumber value: 3) right: (ENumber value: 2))) • > 7 • Evaluator>>evaluate: anExpression • ^ anExpression acceptVisitor: self

  16. Evaluator • Evaluator>>visitNumber: aNumber • ^ aNumber value • Evaluator>>visitPlus: anExpression • |l r| • l := anExpression left acceptVisitor: self. • r := anExpression right acceptVisitor: self. • ^ l + r • Evaluator>>visitPlus: anExpression • |l r| • l := anExpression left acceptVisitor: self. • r := anExpression right acceptVisitor: self. • ^ l * r

  17. Printer • Visitor subclass: #Printer • iv: ‘stream level’ • Printer>>visitNumber: aNumber • stream nextPutAll: aNumber value asString • Printer>>visitPlus: anExpression • stream nextPutAll: ‘+’. • anExpression left acceptVisitor: self. • anExpression right acceptVisitor: self. • Printer>>visitPlus: anExpression • stream nextPutAll: ‘*’. • anExpression left acceptVisitor: self. • anExpression right acceptVisitor: self.

  18. Smalltalk’s class extensions • Smalltalk has class extensions: • method addition • method replacement • So ‘Decoupling’ actions from items can be done: • e.g., put all the printing methods together. • take care: works only for methods • makes it also really easy to package a visitor! • Note: this is a static solution!

  19. Controlling the traversal • Somewhere in the visitor, items are traversed. • Different places where the traversal can be implemented: • in the visitor • on the items hierarchy

  20. Traversal on the Visitor

  21. Traversal on the Items

  22. Granularity of Visit Methods • Sometimes you can represent contextual information by having more specialized visit methods • So visitors have more information for implementing their operations

  23. Granularity of Visit Methods • doNode: is invoked from doVariables: and doSequence:temporaries:statements:

  24. Refined Granularity • Here doTemporaryVariable: provides the context for treating doVariable:

  25. Implementation Tricks • You can implement it as we have shown before. • But notice the general structure of the methods! • This can be taken as advantage: • code can be generated for a visitor. • the method can be performed/invoked • But take care: • only works when there is a full correspondence. • can make the code hard to understand.

  26. Using #perform:

  27. When to Use a Visitor • Use a Visitor: • when the operations on items change a lot. • Do not use a visitor: • when the items you want to visit change a lot. • Question: But how do we know what to choose up-front?

More Related