Talk:Visitor pattern

message: I propose to remove codeproject.com from the Other links. It has 110 links on Wikipedia raising the issues of advertising, promotion, spamming, and just plain over-linking. Comments anyone?
--C# Online.NET Editor 14:51, 12 February 2007 (UTC)
thread_title:  codeproject.com link removal 

message: I've created and added a UML diagram to the article. Let me know if its semi-decent. I come from a Java/C++ background, so I don't know if the diagram applies to the other languages as ubiquitously as I've assumed. I also tried uploading the original .dia file so the image my be edited easily if needed, but it complained that it wasn't a recommended image format :-/ If you want it, just drop me a line. It's not rocket-science, but it does take some time to do all that clicking. The Extremist 10:08, 9 December 2005 (UTC)
replies: text: please post it here so that we can discuss it :-) MatthieuWiki 17:26, 13 July 2007 (UTC)
thread_title:  UML 

message: These examples have gotten out of hand. There need only be one example of this; more than one adds nothing about the pattern itself. I propose it get cut back to just one of the Java, C++, Python, or C# example, and the rest get moved to Wikibooks. Thoughts? —Ben FrantzDale 03:16, 22 May 2006 (UTC)
replies: text: These examples are still out of hand. I still think Java is the best example language for this since it is strongly typed and has garbage collection so all of the pertinent details are explicit and all of the nuisance things (memory allocation) aren't needed. (FWIW, I'm not a fan of Java; I barely know Java and like C++ and Python.) If it weren't for the fact that strong typing goes well with OO design patterns, I'd go for Python for its similarity to pseudocode, but I think things would be lost for this example without typed arguments and without proper abstract base class. At the risk of re-starting an edit war, I'm going to be bold. —Ben FrantzDale (talk) 00:55, 8 April 2009 (UTC)
thread_title:  Examples 

message: As I understand the visitor pattern, shouldn't the the Accept method of the Car class call  Accept on the Body, Engine, and all the wheels? —The preceding unsigned comment was added by 217.166.1.202 (talk) 10:20, 26 February 2007 (UTC)
replies: text: I agree with the above comment. The responsibility of a visitable object is to provide navigation to sub-components. A visitor would only be interested in adding extended functionality to individual nodes and should not be aware of how the nodes are linked. This is the responsibility of the aggregated object itself. --Pav007 11:53, 14 March 2007 (UTC)
replies: text:  I don't have Patterns in front of me, but I believe it can go either way. —Ben FrantzDale 12:05, 14 March 2007 (UTC)
replies: text:  It does seem to contradict the article though, which says: "In the simplest version, where each algorithm needs to iterate in the same way, the accept() method of a container element, in addition to calling back the visit() method of the visitor, also passes the visitor object to the accept() method of all its constituent child elements". Now, this implies that things can be different (needs clarification, by the way), but one would hope that the example should demonstrate the "simplest version" anyway. So i'm going ahead and fixing it. -- int19h 17:24, 15 March 2007 (UTC)
replies: text:  The article also says that: "the visitor design pattern is a way of separating an algorithm from an object structure upon which it operates". So, according to this, visitor is the algorithm (operations), and the car is the structure upon which it operates. The point is that algorithm (the visitor) should not know about the structure. Thus, the car should define its structure for the algorithm, and the initial call visitor.visitCar(car) should be replaced with car.accept(visitor), where car should call accept(visitor) for each its element.  —Preceding unsigned comment added by 77.123.143.133 (talk) 07:20, 26 November 2008 (UTC)
replies: text:  It is true that the visitor pattern can be interpreted in both of these ways (I prefer a visitable Car which calls accept on its parts). But implementing the traversal in each of the Visitors is a clear violation of the DRY principle. If the car stays not beeing visitable, there should at least be an ordinary function (not member) VisitCar which implements the traversal.  —Preceding unsigned comment added by 93.190.250.146 (talk) 07:58, 22 July 2009 (UTC)

text:  As it stands, the Visitor pattern is one of the least undertood and Wikipedia should serve as a reference in this respect. If there are differing views they should be presented. Some sources do state that this pattern should be used to add an operation without changing the elements it operates on. --JamesPoulson (talk) 20:18, 15 August 2011 (UTC)

text:  Update: This Javaworld article describes a more flexible approach to using this pattern. It would be impratical to modify standard classes such as String so what is done is to wrap the target class inside another which implements Visitable/accept interface. This avoids having to modify an element. --JamesPoulson (talk) 22:17, 15 August 2011 (UTC)
thread_title:  Car class in example is wrong? 

message: Given that the D example adds nothing that the Java one doesn't, I'm removing it.  All it does is illustrate the D language, which isn't the point of this particular article. Matthew0028 02:58, 19 June 2007 (UTC)
thread_title:  Duplicate examples in different languages 

message: In my opinion the c++ code example needs to be rewritten or removed. Some issues: There's member variables in the public interface, the classes are guaranteed to leak since there's no destructors and no way to obtain pointers to the dynamically allocated memory. The Microsoft-specific "stdafx.h" precompiled header file is included. Const-correctness is not exercised. std::string objects are passed by value. A temporary iterator is stored as a member. "using namespace std;" is placed is one of the header files. I have put up a cleanup template for now. Ufretin 15:17, 3 October 2007 (UTC)
thread_title:  C++ example is badly coded 

message: I'm not sure if expressions like "If I have a bunch of classes" are very encyclopedic. Also things like "The idea is to" is something you might see in a newsgroup post or an informal publication, not in an encyclopedia. Wopr (talk) 14:46, 9 March 2008 (UTC)
thread_title:  Unencyclopedic language 

message: please fixme if i am wrong. i was thinking about it and i realized that this "visitor" thing can mean "unification".
color_t blue, red, green; // initialize somewhere
draw_dot(red); // each color is different "object"
// versus
enum color_e { BLUE, RED, GREEN, NUM_COLORS };
color_t color[NUM_COLORS];
draw_dot(color[RED]); // colors are accesed as one *color
this example shows that colors are unified. but visitor is more about hoisting up same behaviour, which changes with given context. 
i'd like to have it clear. Xchmelmilos (talk) 18:27, 11 March 2008 (UTC)
thread_title:  Similar concept? 

message: The narrative indicates that the Car class would call the visitor on itself, and then on each of its elements (thus the visitor need not know the structure of the Car class). The example as coded does not reflect this structure, thus providing a misleading example. I can correct this, but will first just serve notice and let the original example provider correct the code if he/she is so inclined. NedHorvath 06:42, 20 September 2008 (UTC)
thread_title:  Example doesn't match narrative 

message: Whether 0 or NULL should be used where a null pointer constant is required is a style issue, and open to debate. It is however, irrelevant to the changes being made to the example source code, because a pure-specifier has nothing to do with pointers at all. The claim that 0 would not be fully portable is exactly backwards.
As stated in my initial edit summary, a pure-specifier shall always be " = 0".ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §9.2 Class members [class.mem] On certain implementations, "= NULL" may compile, if NULL happens to be #defined to 0, It may just as well be #defined to (2-2) or 0L,ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §18.1 Types [lib.support.types] para. 4ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §4.10 Pointer conversions [conv.ptr] para. 1 which is not a valid pure-specifier, even if some compilers may (erroneously) accept 0L or 0x0.http://gcc.gnu.org/ml/gcc-patches/2004-02/msg02318.html Again, a pure-specifier is completely unrelated to null pointer constants, and must be " = 0". decltype (talk) 08:55, 7 April 2009 (UTC)
replies: text: Your ride. I viewed it as an pointer and thats not quite ride. --Alfatrion (talk) 17:15, 7 April 2009 (UTC)
thread_title:  Using NULL as a pure-specifier 

message: I regret to say that this is one of the most opaque explanations I have ever read. It does not really explain it at all. Any article that you have to re-read to understand what it's trying to explain has failed.  —Preceding unsigned comment added by Curmudgeon99 (talk • contribs) 11:25, 6 April 2010 (UTC)
replies: text: If you could provide some more specific criticisim, I'm sure people would be happy to improve it. Is there anything particular you found opaque? —Ben FrantzDale (talk) 15:33, 6 April 2010 (UTC)

text: I've found lots of different explanations about the Visitor Pattern in the Internet. Actually, there are several variations of the pattern, which try to address problems not properly covered by the classical solution proposed to it. In particular, I find implementations full of visitA, visitB, visitWhatever, acceptA, acceptB, acceptWhatever absolutely wrong, IMHO. I've written an article which exposes real world use cases, uncovering why this pattern is needed and how it should be implemented in order to scale, still being clean, neat and absolutely flexible. My article is available here. If you guys find something useful, please feel free to copy and that's it. Thanks Frgomes (talk) 23:56, 29 January 2011 (UTC)
thread_title:  Confusion 

message: Two lines in the car example have accompanying comments:
interface CarElement {
    void accept(CarElementVisitor visitor); // CarElements have to provide accept().
}
and
return elements.clone(); // Return a copy of the array of references.
Each comment is literally an English transliteration of the meaning of the code near it. Comments that merely recapitulate the meaning of the code they adorn are worthless, except possibly to a reader who's unfamiliar with the programming language in which the code is written. Anyone who knows Java already has all the information these comments convey, because it's plainly apparent from the source code itself.
Not wanting to passive-aggressively remove the comments myself, I'm leaving this message here instead, imploring whoever wrote the code to remove them.
71.197.144.116 (talk) 05:14, 25 May 2010 (UTC)
replies: text: I would defend the second as the reader might not know java very well hence not knowing about the clone method. For the fisrt I would consider changing it to 
interface CarElement {
    void accept(CarElementVisitor visitor); // CarElements must provide an accept method.
}
just to reinforce that the interface establishes a contract for classes that implement it.--Salix (talk): 08:52, 25 May 2010 (UTC)
thread_title:  Vacuous comments 

message: It is not correct to say that the visitor pattern "adds" functionality or "adds" virtual functions to the object or object structure. Doing so implies that dynamic modification is occurring. That is incorrect and therefore misleading...
The Visitor patterns simply walks an object structure and performs (visits) an operation on each element of that structure. That's it.
There are many ways this "visit" may occur. For example, the visit may...
# perform the operation directly against each element by casting it (explicitly or implicitly) to a common interface or parent type shared by all the elements in the structure;
# perform the operation directly against each element with a procedure that detects and applies a type specific operation to each element; or
# pass a delegate, function pointer, or object hosting the operation as a method or set of type specific methods to each element through a common procedure (defined by a common parent interface or type) which then invokes the provided operation to do whatever it does.
The visitor pattern is a simple concepts. It is useful to have a simple example to bring that fact home...
://defines the delegate or function point, Action, which accepts a Visitable element and returns void or nothing
:delegate void Action( Visitable actionable )
://defines the class Visitable which supports visits through a Perform method
:class Visitable
::public void Perform( Action action)
:::action(this)
:items = List Of Visitable{"Cat", "Dog", "Ball", 1, 5, 123, 3.14, new Image("c:\folder\image1.jpg")}
:foreach( element in items )
::element.Perform( delegate(e) {if (e is Numeric) e.ToString.Print else e.Print } )
Here, the conforming parent type, Visitable, has an Action method which accepts a delegate as the visitor operation. Action is expected to invoke the delegate, passing it's containing element. In this case, the delegate will query the type and perform an appropriate operation.
I believe this is a better explanation because it does not presume a great deal of prior knowledge (one of the purposes of explanations in general). Subsequently, a more in depth treatment may be pursued with greater success with a reader who has a stable rock solid foundation.  —Preceding unsigned comment added by 174.114.248.239 (talk) 18:18, 30 May 2010 (UTC)
thread_title:  Terminology and Perspective Problem 

message: Like many of the people that have left comments here, I'm having a hard time understanding this article. But it seems like these are just fancy iterators. Am I wrong? 24.130.212.167 (talk) 08:03, 31 January 2012 (UTC)
replies: text: They are related in that both are traversal patterns, but they are different. Using a visitor is a complementary approach to doing something with a collection of objects. In particular, a core idea of the visitor pattern is that you can prescribe different operations for different polymorphic (or static) types you visit. Also, with the visitor pattern, different objects have control over traversal order. For example, in Boost, you'll see visitors used for doing operations on heterogeneous statically-typed collections such as a std::pair<T,U>. You can't just iterate over a std::pair<T,U> because it has two different types, but you can apply a visitor that knows what to do with Ts and Us. The usual usage, though, is for polymorphic types. —Ben FrantzDale (talk) 14:28, 31 January 2012 (UTC)
thread_title:  Are these just fancy iterators 

message: In the UML class diagram, the Visitor class implements the Visitable interface. In my opinion, this is bogus, language-wise. If something is "visitable", then it gets visited, it does not visit. It is the passive part. As such, the element being visited can be called "visitable", but not the visiting object (the visitor). 129.69.215.1 (talk) 10:49, 2 May 2013 (UTC)
replies: text: Well spotted. The image is based on :File:VisitorClassDiagram.png which uses Visitor for the interface and ConcreteVisitor for the implementing class. The new :File:VisitorClassDiagram.svg was  changed from a correct version  last year. I've reverted the change to the image.--Salix (talk): 11:50, 2 May 2013 (UTC)
thread_title:  Naming in UML Diagram 

message: Are you sure that Function overloading is required for the Visitor Pattern? Couldn't I just give the functions individual names, e.g. visitTypeA(TypeA a), visitTypeB(TypeB b).. instead of visit(TypeA a), visit(TypeB b). I don't think that missing function overloading hinders the implementation of this pattern. Ghinrael (talk) 12:29, 20 July 2013 (UTC)
replies: text: I believe this is correct. The generic C++ code in the Implementation section in GOF is styled the same way using function names "VisitElementA(ElementA*)" and "VisitElementB(ElementB*)". - rfrankla (talk) 11:50, 21 April 2014 (UTC)
thread_title:  Function Overloading required 

message: Is the Scala example correct? It isn't using double dispatch but instead just switching on the types, which contradicts both "The visitor takes the instance reference as input, and implements the goal through double dispatch" and "Another problem with [the naive] approach is that it is very easy to miss a shape in one or more savers, or a new primitive shape is introduced but the save routine is implemented only for one file type and not others, leading to code extension and maintenance problems. Instead, one could apply the Visitor pattern". I believe both those statements are correct, and that the Scala example does not properly demonstrate the visitor pattern. I know enough Scala to fix the example, if people agree, but I also would be in favour of removing it entirely as I don't think another example adds much to the article. Thoughts? ZoFreX (talk) 16:28, 23 June 2014 (UTC)
replies: text: I've removed it entirely. I can't see what benefit adding another language implementation gives.--Salix alba (talk): 16:37, 23 June 2014 (UTC)
thread_title:  Scala example 

message: This article exhibits blatant plagiarism of the cited external link. In the "Definition" section we have:
"The Gang of Four defines the Visitor as: "Represent an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates."—″≤
The nature of the Visitor makes it an ideal pattern to plug into public APIs thus allowing its clients to perform operations on a class using a “visiting” class without having to modify the source."
and now compare this to the text at :
"The Gang of Four defines the Visitor as:
Represent an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
The very nature of the Visitor makes it an ideal pattern to plug into public API’s, thus allowing its clients to perform operations on a class using a “visiting” class without having to modify the source..."
Outrageous!  — Preceding unsigned comment added by 87.82.250.210 (talk) 14:10, 7 January 2015 (UTC)
thread_title:  plagiarism 

message: In the state section of the article, a pretty printing example is references, however it's not actually included in the article, or linked to anywhere. Has this been accidentally removed or does this text accidentally remain?
9point6 (talk) 20:19, 3 February 2015 (UTC)
thread_title:  Pretty Printing Example 

message: Isn't this:
* Visiting body
* Visiting engine
* Visiting car
* ...
* Moving my body
* Starting my engine
* Starting my car
Supposed to read:
* Visiting engine
* Visiting body
* Visiting car
* ...
* Starting my engine
* Moving my body
* Starting my car
or am I trippin? — Preceding unsigned comment added by 54.240.196.185 (talk • contribs) 
:I don't think so. If you look at the Car constructor we have
:
this.elements = new ICarElement[] { new Wheel("front left"),
            new Wheel("front right"), new Wheel("back left") ,
            new Wheel("back right"), new Body(), new Engine() };
:so the body comes before the engine. --Salix alba (talk): 05:47, 5 November 2015 (UTC)
thread_title:  Typo in Java example Output? 

message: Regarding the tip for using reflection to implement a default visitor method found in the External links as "Article Java Tip 98: Reflect on the Visitor design pattern" — am I correct in thinking this is obsolete in Java 1.8, where interfaces may have default methods? Labalius (talk) 17:05, 8 November 2015 (UTC)
replies: text: The link was dead, but the article can be found on info world at . As its outdated I've removed the comment and external link.--Salix alba (talk): 08:34, 30 June 2020 (UTC)
thread_title:  Article Java Tip 98 is obsolete as of Java 1.8 

message: C# example STILL not a visitor pattern. The expressionprintervisitor should be a subclass of an abstract visitor. The example required that expressions know about printing. This is not what visitor is about.  — Preceding unsigned comment added by 85.160.45.240 (talk) 00:22, 10 November 2021 (UTC)
replies: text: OK I've removed the section. Is the dynamic example OK? --Salix alba (talk): 07:21, 30 June 2020 (UTC)
replies: text: No, that example failed at runtime, didn't compile, and didn't use the Visitor pattern. I fixed it for you. 99.16.142.154 (talk) 16:08, 23 August 2020 (UTC)

text: I looked into it more: it works on .NET Core but not .NET Framework because none of your types are public. .NET Framework wants dynamic to use public methods, .NET Core is more YOLO. I think if we're trying to teach people a design pattern we should shy away from fanciness like this! 99.16.142.154 (talk) 12:47, 25 August 2020 (UTC)
thread_title:  C# "classic" example doesn't use visitor pattern 

message: The current Smalltalk example delegates the behavior to each object rather than separating the logic in a visitor? The following tweaked version puts the printing logic into the ExpressionPrinterVisitor rather than in each Expression subclass:
"There's no syntax for creating a class. Classes are created by sending messages to other classes."
WriteStream subclass: #ExpressionPrinterVisitor
    instanceVariableNames: ''
    classVariableNames: ''
    package: 'Wikipedia'.
ExpressionPrinterVisitor>>write: anExpression
    "Visit given expression"
    ^ anExpression accept: self.
ExpressionPrinterVisitor>>visitLiteral: aLiteral
    "Print a Literal object"
    self nextPutAll: aLiteral value asString.
ExpressionPrinterVisitor>>visitAddition: anAddition
    "Print an Addition object"
    self
        nextPut: $(;
        nextPutAll: anAddition left asString;
        nextPut: $+;
        nextPutAll: anAddition right asString;
        nextPut: $).
Object subclass: #Expression
    instanceVariableNames: ''
    classVariableNames: ''
    package: 'Wikipedia'.
Expression subclass: #Literal
    instanceVariableNames: 'value'
    classVariableNames: ''
    package: 'Wikipedia'.
Literal class>>with: aValue
    "Class method for building an instance of the Literal class"
    ^ self new
        value: aValue;
        yourself.
Literal>>value: aValue
  "Setter for value"
  value := aValue.
Literal>>value
  "Getter for value"
  ^ value.
Literal>>accept: aVisitor
    "Delegate behaviour to visitor which must implement visitLiteral"
    ^aVisitor visitLiteral: self.
Expression subclass: #Addition
    instanceVariableNames: 'left right'
    classVariableNames: ''
    package: 'Wikipedia'.
Addition class>>left: a right: b
    "Class method for building an instance of the Addition class"
    ^ self new
        left: a;
        right: b;
        yourself.
Addition>>left: anExpression
    "Setter for left"
    left := anExpression.
Addition>>left
    "Getter for left"
    ^ left.
Addition>>right: anExpression
    "Setter for right"
    right := anExpression.
Addition>>right
    "Getter for right"
    ^ right.
Addition>>accept: aVisitor
    "Delegate behaviour to visitor which must implement visitAddition"
    ^aVisitor visitAddition: self.
Object subclass: #Program
    instanceVariableNames: ''
    classVariableNames: ''
    package: 'Wikipedia'.
Program>>main
    | expression stream |
    expression := Addition
                    left: (Addition
                            left: (Literal with: 1)
                            right: (Literal with: 2))
                    right: (Literal with: 3).
    stream := ExpressionPrinterVisitor on: (String new: 100).
    stream write: expression.
    Transcript show: stream contents.
    Transcript flush.
This way if any new program logic needs to be added, a new visitor class can be created which uses the visitLiteral or visitAddition selectors rather than having to alter the Literal or Addition classes. Smalltalker2 (talk) 17:35, 22 January 2022 (UTC)
replies: text: Both are a bit complex and can be simplified. On the other hand, I would make a separate class for each entity:  and  and invoke accordingly. It's good to break down example into steps, so it's easier to consume. AXONOV (talk) ⚑ 13:05, 26 January 2022 (UTC)

text: Breaking down the above:
In Smalltalk we can first define Expression objects:
"There's no syntax for creating a class. Classes are created by sending messages to other classes."
Object subclass: #Expression
    instanceVariableNames: ''
    classVariableNames: ''
    package: 'Wikipedia'.
These can be sub-classed to useful types such as a literal expression type, which must respond to the #accept: method:
Expression subclass: #Literal
    instanceVariableNames: 'value'
    classVariableNames: ''
    package: 'Wikipedia'.
Literal class>>with: aValue
    "Class method for building an instance of the Literal class"
    ^ self new
        value: aValue;
        yourself.
Literal>>value: aValue
  "Setter for value"
  value := aValue.
Literal>>value
  "Getter for value"
  ^ value.
Literal>>accept: aVisitor
    "Delegate behaviour to visitor which must implement visitLiteral"
    ^aVisitor visitLiteral: self.
And similarly for an addition expression type:
Expression subclass: #Addition
    instanceVariableNames: 'left right'
    classVariableNames: ''
    package: 'Wikipedia'.
Addition class>>left: a right: b
    "Class method for building an instance of the Addition class"
    ^ self new
        left: a;
        right: b;
        yourself.
Addition>>left: anExpression
    "Setter for left"
    left := anExpression.
Addition>>left
    "Getter for left"
    ^ left.
Addition>>right: anExpression
    "Setter for right"
    right := anExpression.
Addition>>right
    "Getter for right"
    ^ right.
Addition>>accept: aVisitor
    "Delegate behaviour to visitor which must implement visitAddition"
    ^aVisitor visitAddition: self.
Then to add new logic separate from these existing classes (and without the need to modify their structure) we can define a visitor, for example for printing:
WriteStream subclass: #ExpressionPrinterVisitor
    instanceVariableNames: ''
    classVariableNames: ''
    package: 'Wikipedia'.
ExpressionPrinterVisitor>>write: anExpression
    "Visit given expression"
    ^ anExpression accept: self.
ExpressionPrinterVisitor>>visitLiteral: aLiteral
    "Print a Literal object"
    self nextPutAll: aLiteral value asString.
ExpressionPrinterVisitor>>visitAddition: anAddition
    "Print an Addition object"
    self
        nextPut: $(;
        nextPutAll: anAddition left asString;
        nextPut: $+;
        nextPutAll: anAddition right asString;
        nextPut: $).
Here the visitor needs to define methods #visitLiteral and #visitAddition in order to be accessed by the original expression objects. Finally we can use these objects to print an expression:
Object subclass: #Program
    instanceVariableNames: ''
    classVariableNames: ''
    package: 'Wikipedia'.
Program>>main
    | expression stream |
    expression := Addition
                    left: (Addition
                            left: (Literal with: 1)
                            right: (Literal with: 2))
                    right: (Literal with: 3).
    stream := ExpressionPrinterVisitor on: (String new: 100).
    stream write: expression.
    Transcript show: stream contents.
    Transcript flush.
This could benefit from further description but I think the logic is clearer Smalltalker2 (talk) 17:48, 26 January 2022 (UTC)

text: Good job. Do we have sources on where these "Expression/Left/Right" were all taken? As I see every example basically implements the code... Any thoughts? AXONOV (talk) ⚑ 07:40, 27 January 2022 (UTC)
thread_title:  Suggested change to the Smalltalk example to satisfy the visitor pattern