27
Stéphane Ducasse 1 Stéphane Ducasse [email protected] http://stephane.ducasse.fre e.fr/ Visitor

Stoop 431-visitor

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Stoop 431-visitor

Stéphane Ducasse 1

Stéphane [email protected]://stephane.ducasse.free.fr/

Visitor

Page 2: Stoop 431-visitor

S.Ducasse 2

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.

Visitor Intent

Page 3: Stoop 431-visitor

S.Ducasse 3

Visitor Possible Structure

Page 4: Stoop 431-visitor

S.Ducasse 4

Whenever you have a number of items on which you have to perform a number of actionsWhen 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

When to use a Visitor

Page 5: Stoop 431-visitor

S.Ducasse 5

So all our problems are solved, no?Well...how to define itwhen to use a visitorcontrol over item traversalchoosing the granularity of visitor methodsimplementation tricks

Applying the Visitor

Page 6: Stoop 431-visitor

S.Ducasse 6

Language to deal with arithmetic expressions.

It supports one kind of number, and has +, *, (, )

We want to evaluate expressions, and print them.

Visitor Toy Example

Page 7: Stoop 431-visitor

S.Ducasse 7

ExampleEvaluating 1 + 1 gives = 2

1 + (3 * 2)gives 7

Printing+1*32

Page 8: Stoop 431-visitor

S.Ducasse 8

Visitor Toy Example: ParseTree

Page 9: Stoop 431-visitor

S.Ducasse 9

Expressions creation1ENumber 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 noneed of ENumber value:.....

Page 10: Stoop 431-visitor

S.Ducasse 10

Two solutions:add methods for evaluating, printing, ... on Expression and its subclassescreate a Visitor, add the visit methods on Expression and its subclasses, and implement visitors for evaluation, printing, ...

Implementing the Actions

Page 11: Stoop 431-visitor

S.Ducasse 11

Visitor Toy Example Solution 1

Page 12: Stoop 431-visitor

S.Ducasse 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

Page 13: Stoop 431-visitor

S.Ducasse 13

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 treebehavior of the printer are mixed with expressions

Limits of the approach

Page 14: Stoop 431-visitor

S.Ducasse 14

Visitor Toy Example 2

Page 15: Stoop 431-visitor

S.Ducasse 15

Expressions creationEvaluator 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

Page 16: Stoop 431-visitor

S.Ducasse 16

EvaluatorEvaluator>>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

Page 17: Stoop 431-visitor

S.Ducasse 17

PrinterVisitor 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.

Page 18: Stoop 431-visitor

S.Ducasse 18

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

Smalltalk’s class extensions

Page 19: Stoop 431-visitor

S.Ducasse 19

Somewhere in the visitor, items are traversed.Different places where the traversal can be implemented:in the visitoron the items hierarchy

Controlling the traversal

Page 20: Stoop 431-visitor

S.Ducasse 20

Traversal on the Visitor

Page 21: Stoop 431-visitor

S.Ducasse 21

Traversal on the Items

Page 22: Stoop 431-visitor

S.Ducasse 22

Sometimes you can represent contextual information by having more specialized visit methods

So visitors have more information for implementing their operations

Granularity of Visit Methods

Page 23: Stoop 431-visitor

S.Ducasse 23

doNode: is invoked from doVariables: and doSequence:temporaries:statements:

Granularity of Visit Methods

Page 24: Stoop 431-visitor

S.Ducasse 24

Here doTemporaryVariable: provides the context for treating doVariable:

Refined Granularity

Page 25: Stoop 431-visitor

S.Ducasse 25

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/invokedBut take care:only works when there is a full correspondence.can make the code hard to understand.

Implementation Tricks

Page 26: Stoop 431-visitor

S.Ducasse 26

Using #perform:

Page 27: Stoop 431-visitor

S.Ducasse 27

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?

When to Use a Visitor