of visitors to interact with the elements based on the dynamic types of both the elements and the visitors. C# example This example declares a separate ExpressionPrintingVisitor class that takes care of the printing. namespace Wikipedia; public class ExpressionPrintingVisitor { public void PrintLiteral(Literal literal) { Console.WriteLine(literal.Value); } public void PrintAddition(Addition addition) { double leftValue = addition.Left.GetValue(); double rightValue = addition.Right.GetValue(); var sum = addition.GetValue(); Console.WriteLine("{0} + {1} = {2}", leftValue, rightValue, sum); } } public abstract class Expression { public abstract void Accept(ExpressionPrintingVisitor v); public abstract double GetValue(); } public class Literal : Expression { public double Value { get; set; } public Literal(double value) { this.Value = value; } public override void Accept(ExpressionPrintingVisitor v) { v.PrintLiteral(this); } public override double GetValue() { return Value; } } public class Addition : Expression { public Expression Left { get; set; } public Expression Right { get; set; } public Addition(Expression left, Expression right) { Left = left; Right = right; } public override void Accept(ExpressionPrintingVisitor v) { Left.Accept(v); Right.Accept(v); v.PrintAddition(this); } public override double GetValue() { return Left.GetValue() + Right.GetValue(); } } public static class Program { public static void Main(string[] args) { // Emulate 1 + 2 + 3 var e = new Addition( new Addition( new Literal(1), new Literal(2) ), new Literal(3) ); var printingVisitor = new ExpressionPrintingVisitor(); e.Accept(printingVisitor); } } Smalltalk example In this case, it is the object's responsibility to know how to print itself on a stream. The visitor here is then the object, not the stream. "There's no syntax for creating a class. Classes are created by sending messages to other classes." WriteStream subclass: #ExpressionPrinter instanceVariableNames: '' classVariableNames: '' package: 'Wikipedia'. ExpressionPrinter>>write: anObject "Delegates the action to the object. The object doesn't need to be of any special class; it only needs to be able to understand the message #putOn:" anObject putOn: self. ^ anObject. 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>>putOn: aStream "A Literal object knows how to print itself" aStream nextPutAll: value asString. 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: