Visitor pattern

Last updated

A visitor pattern is a software design pattern that separates the algorithm from the object structure. Because of this separation, new operations can be added to existing object structures without modifying the structures. It is one way to follow the open/closed principle in object-oriented programming and software engineering.

Contents

In essence, the visitor allows adding new virtual functions to a family of classes, without modifying the classes. Instead, a visitor class is created that implements all of the appropriate specializations of the virtual function. The visitor takes the instance reference as input, and implements the goal through double dispatch.

Programming languages with sum types and pattern matching obviate many of the benefits of the visitor pattern, as the visitor class is able to both easily branch on the type of the object and generate a compiler error if a new object type is defined which the visitor does not yet handle.

Overview

The Visitor [1] design pattern is one of the twenty-three well-known Gang of Four design patterns that describe how to solve recurring design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.

What problems can the Visitor design pattern solve?

When new operations are needed frequently and the object structure consists of many unrelated classes, it's inflexible to add new subclasses each time a new operation is required because "[..] distributing all these operations across the various node classes leads to a system that's hard to understand, maintain, and change." [1]

What solution does the Visitor design pattern describe?

This makes it possible to create new operations independently from the classes of an object structure by adding new visitor objects.

See also the UML class and sequence diagram below.

Definition

The Gang of Four defines the Visitor as:

Represent[ing] 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. [2]

Advantages

Moving operations into visitor classes is beneficial when

A drawback to this pattern, however, is that it makes extensions to the class hierarchy more difficult, as new classes typically require a new visit method to be added to each visitor.

Application

Consider the design of a 2D computer-aided design (CAD) system. At its core, there are several types to represent basic geometric shapes like circles, lines, and arcs. The entities are ordered into layers, and at the top of the type hierarchy is the drawing, which is simply a list of layers, plus some added properties.

A fundamental operation on this type hierarchy is saving a drawing to the system's native file format. At first glance, it may seem acceptable to add local save methods to all types in the hierarchy. But it is also useful to be able to save drawings to other file formats. Adding ever more methods for saving into many different file formats soon clutters the relatively pure original geometric data structure.

A naive way to solve this would be to maintain separate functions for each file format. Such a save function would take a drawing as input, traverse it, and encode into that specific file format. As this is done for each added different format, duplication between the functions accumulates. For example, saving a circle shape in a raster format requires very similar code no matter what specific raster form is used, and is different from other primitive shapes. The case for other primitive shapes like lines and polygons is similar. Thus, the code becomes a large outer loop traversing through the objects, with a large decision tree inside the loop querying the type of the object. Another problem with this 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. As the versions of the same file grows it becomes more complicated to maintain it.

Instead, the visitor pattern can be applied. It encodes the logical operation (i.e. save(image_tree)) on the whole hierarchy into one class (i.e. Saver) that implements the common methods for traversing the tree and describes virtual helper methods (i.e. save_circle, save_square, etc.) to be implemented for format specific behaviors. In the case of the CAD example, such format specific behaviors would be implemented by a subclass of Visitor (i.e. SaverPNG). As such, all duplication of type checks and traversal steps is removed. Additionally, the compiler now complains if a shape is omitted since it is now expected by the common base traversal/save function.

Iteration loops

The visitor pattern may be used for iteration over container-like data structures just like Iterator pattern but with limited functionality. [3] :288 For example, iteration over a directory structure could be implemented by a function class instead of more conventional loop pattern. This would allow deriving various useful information from directories content by implementing a visitor functionality for every item while reusing the iteration code. It's widely employed in Smalltalk systems and can be found in C++ as well. [3] :289 A drawback of this approach, however, is that you can't break out of the loop easily or iterate concurrently (in parallel i.e. traversing two containers at the same time by a single i variable). [3] :289 The latter would require writing additional functionality for a visitor to support these features. [3] :289

Structure

UML class and sequence diagram

A sample UML class diagram and sequence diagram for the Visitor design pattern. W3sDesign Visitor Design Pattern UML.jpg
A sample UML class diagram and sequence diagram for the Visitor design pattern.

In the UML class diagram above, the ElementA class doesn't implement a new operation directly. Instead, ElementA implements a dispatching operationaccept(visitor) that "dispatches" (delegates) a request to the "accepted visitor object" (visitor.visitElementA(this)). The Visitor1 class implements the operation (visitElementA(e:ElementA)).
ElementB then implements accept(visitor) by dispatching to visitor.visitElementB(this). The Visitor1 class implements the operation (visitElementB(e:ElementB)).

The UML sequence diagram shows the run-time interactions: The Client object traverses the elements of an object structure (ElementA,ElementB) and calls accept(visitor) on each element.
First, the Client calls accept(visitor) on ElementA, which calls visitElementA(this) on the accepted visitor object. The element itself (this) is passed to the visitor so that it can "visit" ElementA (call operationA()).
Thereafter, the Client calls accept(visitor) on ElementB, which calls visitElementB(this) on the visitor that "visits" ElementB (calls operationB()).

Class diagram

Visitor in Unified Modeling Language (UML). Visitor design pattern.svg
Visitor in Unified Modeling Language (UML).
Visitor in LePUS3 (legend) Visitor pattern class diagram in LePUS3.gif
Visitor in LePUS3 (legend)

Details

The visitor pattern requires a programming language that supports single dispatch, as common object-oriented languages (such as C++, Java, Smalltalk, Objective-C, Swift, JavaScript, Python and C#) do. Under this condition, consider two objects, each of some class type; one is termed the element, and the other is visitor.

The visitor declares a visit method, which takes the element as an argument, for each class of element. Concrete visitors are derived from the visitor class and implement these visit methods, each of which implements part of the algorithm operating on the object structure. The state of the algorithm is maintained locally by the concrete visitor class.

The element declares an accept method to accept a visitor, taking the visitor as an argument. Concrete elements, derived from the element class, implement the accept method. In its simplest form, this is no more than a call to the visitor's visit method. Composite elements, which maintain a list of child objects, typically iterate over these, calling each child's accept method.

The client creates the object structure, directly or indirectly, and instantiates the concrete visitors. When an operation is to be performed which is implemented using the Visitor pattern, it calls the accept method of the top-level element(s).

When the accept method is called in the program, its implementation is chosen based on both the dynamic type of the element and the static type of the visitor. When the associated visit method is called, its implementation is chosen based on both the dynamic type of the visitor and the static type of the element, as known from within the implementation of the accept method, which is the same as the dynamic type of the element. (As a bonus, if the visitor can't handle an argument of the given element's type, then the compiler will catch the error.)

Thus, the implementation of the visit method is chosen based on both the dynamic type of the element and the dynamic type of the visitor. This effectively implements double dispatch. For languages whose object systems support multiple dispatch, not only single dispatch, such as Common Lisp or C# via the Dynamic Language Runtime (DLR), implementation of the visitor pattern is greatly simplified (a.k.a. Dynamic Visitor) by allowing use of simple function overloading to cover all the cases being visited. A dynamic visitor, provided it operates on public data only, conforms to the open/closed principle (since it does not modify extant structures) and to the single responsibility principle (since it implements the Visitor pattern in a separate component).

In this way, one algorithm can be written to traverse a graph of elements, and many different kinds of operations can be performed during that traversal by supplying different kinds 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. If the introduction of a new concrete visitor is desired, a new class will be created to implement the Visitor interface, and new implementations for the Visit methods will be provided. The existing classes (Literal and Addition) will remain unchanged.

usingSystem;namespaceWikipedia;publicinterfaceVisitor{voidVisit(Literalliteral);voidVisit(Additionaddition);}publicclassExpressionPrintingVisitor:Visitor{publicvoidVisit(Literalliteral){Console.WriteLine(literal.Value);}publicvoidVisit(Additionaddition){doubleleftValue=addition.Left.GetValue();doublerightValue=addition.Right.GetValue();varsum=addition.GetValue();Console.WriteLine("{0} + {1} = {2}",leftValue,rightValue,sum);}}publicabstractclassExpression{publicabstractvoidAccept(Visitorv);publicabstractdoubleGetValue();}publicclassLiteral:Expression{publicLiteral(doublevalue){this.Value=value;}publicdoubleValue{get;set;}publicoverridevoidAccept(Visitorv){v.Visit(this);}publicoverridedoubleGetValue(){returnValue;}}publicclassAddition:Expression{publicAddition(Expressionleft,Expressionright){Left=left;Right=right;}publicExpressionLeft{get;set;}publicExpressionRight{get;set;}publicoverridevoidAccept(Visitorv){Left.Accept(v);Right.Accept(v);v.Visit(this);}publicoverridedoubleGetValue(){returnLeft.GetValue()+Right.GetValue();}}publicstaticclassProgram{publicstaticvoidMain(string[]args){// Emulate 1 + 2 + 3vare=newAddition(newAddition(newLiteral(1),newLiteral(2)),newLiteral(3));varprintingVisitor=newExpressionPrintingVisitor();e.Accept(printingVisitor);Console.ReadKey();}}

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."WriteStreamsubclass:#ExpressionPrinterinstanceVariableNames:''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:"anObjectputOn:self.^anObject.Objectsubclass:#ExpressioninstanceVariableNames:''classVariableNames:''package:'Wikipedia'.Expressionsubclass:#LiteralinstanceVariableNames:'value'classVariableNames:''package:'Wikipedia'.Literalclass>>with:aValue"Class method for building an instance of the Literal class"^selfnewvalue:aValue;yourself.Literal>>value:aValue"Setter for value"value:=aValue.Literal>>putOn:aStream"A Literal object knows how to print itself"aStreamnextPutAll:valueasString.Expressionsubclass:#AdditioninstanceVariableNames:'left right'classVariableNames:''package:'Wikipedia'.Additionclass>>left:aright:b"Class method for building an instance of the Addition class"^selfnewleft:a;right:b;yourself.Addition>>left:anExpression"Setter for left"left:=anExpression.Addition>>right:anExpression"Setter for right"right:=anExpression.Addition>>putOn:aStream"An Addition object knows how to print itself"aStreamnextPut:$(.leftputOn:aStream.aStreamnextPut:$+.rightputOn:aStream.aStreamnextPut:$).Objectsubclass:#PrograminstanceVariableNames:''classVariableNames:''package:'Wikipedia'.Program>>main|expressionstream|expression:=Additionleft: (Additionleft: (Literalwith:1)                             right: (Literalwith:2))                     right: (Literalwith:3).stream:=ExpressionPrinteron: (Stringnew:100).streamwrite:expression.Transcriptshow:streamcontents.Transcriptflush.


Go

Go does not support method overloading, so the visit methods need different names. A typical visitor interface might be

typeVisitorinterface{visitWheel(wheelWheel)stringvisitEngine(engineEngine)stringvisitBody(bodyBody)stringvisitCar(carCar)string}

Java example

The following example is in the language Java, and shows how the contents of a tree of nodes (in this case describing the components of a car) can be printed. Instead of creating print methods for each node subclass (Wheel, Engine, Body, and Car), one visitor class (CarElementPrintVisitor) performs the required printing action. Because different node subclasses require slightly different actions to print properly, CarElementPrintVisitor dispatches actions based on the class of the argument passed to its visit method. CarElementDoVisitor, which is analogous to a save operation for a different file format, does likewise.

Diagram

UML diagram of an example of the Visitor design pattern.png

Sources

importjava.util.List;interfaceCarElement{voidaccept(CarElementVisitorvisitor);}interfaceCarElementVisitor{voidvisit(Bodybody);voidvisit(Carcar);voidvisit(Engineengine);voidvisit(Wheelwheel);}classWheelimplementsCarElement{privatefinalStringname;publicWheel(finalStringname){this.name=name;}publicStringgetName(){returnname;}@Overridepublicvoidaccept(CarElementVisitorvisitor){/*       * accept(CarElementVisitor) in Wheel implements       * accept(CarElementVisitor) in CarElement, so the call       * to accept is bound at run time. This can be considered       * the *first* dispatch. However, the decision to call       * visit(Wheel) (as opposed to visit(Engine) etc.) can be       * made during compile time since 'this' is known at compile       * time to be a Wheel. Moreover, each implementation of       * CarElementVisitor implements the visit(Wheel), which is       * another decision that is made at run time. This can be       * considered the *second* dispatch.       */visitor.visit(this);}}classBodyimplementsCarElement{@Overridepublicvoidaccept(CarElementVisitorvisitor){visitor.visit(this);}}classEngineimplementsCarElement{@Overridepublicvoidaccept(CarElementVisitorvisitor){visitor.visit(this);}}classCarimplementsCarElement{privatefinalList<CarElement>elements;publicCar(){this.elements=List.of(newWheel("front left"),newWheel("front right"),newWheel("back left"),newWheel("back right"),newBody(),newEngine());}@Overridepublicvoidaccept(CarElementVisitorvisitor){for(CarElementelement:elements){element.accept(visitor);}visitor.visit(this);}}classCarElementDoVisitorimplementsCarElementVisitor{@Overridepublicvoidvisit(Bodybody){System.out.println("Moving my body");}@Overridepublicvoidvisit(Carcar){System.out.println("Starting my car");}@Overridepublicvoidvisit(Wheelwheel){System.out.println("Kicking my "+wheel.getName()+" wheel");}@Overridepublicvoidvisit(Engineengine){System.out.println("Starting my engine");}}classCarElementPrintVisitorimplementsCarElementVisitor{@Overridepublicvoidvisit(Bodybody){System.out.println("Visiting body");}@Overridepublicvoidvisit(Carcar){System.out.println("Visiting car");}@Overridepublicvoidvisit(Engineengine){System.out.println("Visiting engine");}@Overridepublicvoidvisit(Wheelwheel){System.out.println("Visiting "+wheel.getName()+" wheel");}}publicclassVisitorDemo{publicstaticvoidmain(finalString[]args){Carcar=newCar();car.accept(newCarElementPrintVisitor());car.accept(newCarElementDoVisitor());}}


Output

Visiting front left wheel Visiting front right wheel Visiting back left wheel Visiting back right wheel Visiting body Visiting engine Visiting car Kicking my front left wheel Kicking my front right wheel Kicking my back left wheel Kicking my back right wheel Moving my body Starting my engine Starting my car 

Common Lisp example

Sources

(defclassauto()((elements:initarg:elements)))(defclassauto-part()((name:initarg:name:initform"<unnamed-car-part>")))(defmethodprint-object((pauto-part)stream)(print-object(slot-valuep'name)stream))(defclasswheel(auto-part)())(defclassbody(auto-part)())(defclassengine(auto-part)())(defgenerictraverse(functionobjectother-object))(defmethodtraverse(function(aauto)other-object)(with-slots(elements)a(dolist(eelements)(funcallfunctioneother-object))));; do-something visitations;; catch all(defmethoddo-something(objectother-object)(formatt"don't know how ~s and ~s should interact~%"objectother-object));; visitation involving wheel and integer(defmethoddo-something((objectwheel)(other-objectinteger))(formatt"kicking wheel ~s ~s times~%"objectother-object));; visitation involving wheel and symbol(defmethoddo-something((objectwheel)(other-objectsymbol))(formatt"kicking wheel ~s symbolically using symbol ~s~%"objectother-object))(defmethoddo-something((objectengine)(other-objectinteger))(formatt"starting engine ~s ~s times~%"objectother-object))(defmethoddo-something((objectengine)(other-objectsymbol))(formatt"starting engine ~s symbolically using symbol ~s~%"objectother-object))(let((a(make-instance'auto:elements`(,(make-instance'wheel:name"front-left-wheel"),(make-instance'wheel:name"front-right-wheel"),(make-instance'wheel:name"rear-left-wheel"),(make-instance'wheel:name"rear-right-wheel"),(make-instance'body:name"body"),(make-instance'engine:name"engine")))));; traverse to print elements;; stream *standard-output* plays the role of other-object here(traverse#'printa*standard-output*)(terpri);; print newline;; traverse with arbitrary context from other object(traverse#'do-somethinga42);; traverse with arbitrary context from other object(traverse#'do-somethinga'abc))

Output

"front-left-wheel" "front-right-wheel" "rear-left-wheel" "rear-right-wheel" "body" "engine" kicking wheel "front-left-wheel" 42 times kicking wheel "front-right-wheel" 42 times kicking wheel "rear-left-wheel" 42 times kicking wheel "rear-right-wheel" 42 times don't know how "body" and 42 should interact starting engine "engine" 42 times kicking wheel "front-left-wheel" symbolically using symbol ABC kicking wheel "front-right-wheel" symbolically using symbol ABC kicking wheel "rear-left-wheel" symbolically using symbol ABC kicking wheel "rear-right-wheel" symbolically using symbol ABC don't know how "body" and ABC should interact starting engine "engine" symbolically using symbol ABC

Notes

The other-object parameter is superfluous in traverse. The reason is that it is possible to use an anonymous function that calls the desired target method with a lexically captured object:

(defmethodtraverse(function(aauto));; other-object removed(with-slots(elements)a(dolist(eelements)(funcallfunctione))));; from here too;; ...;; alternative way to print-traverse(traverse(lambda(o)(printo*standard-output*))a);; alternative way to do-something with;; elements of a and integer 42(traverse(lambda(o)(do-somethingo42))a)

Now, the multiple dispatch occurs in the call issued from the body of the anonymous function, and so traverse is just a mapping function that distributes a function application over the elements of an object. Thus all traces of the Visitor Pattern disappear, except for the mapping function, in which there is no evidence of two objects being involved. All knowledge of there being two objects and a dispatch on their types is in the lambda function.

Python example

Python does not support method overloading in the classical sense (polymorphic behavior according to type of passed parameters), so the "visit" methods for the different model types need to have different names.

Sources

"""Visitor pattern example."""fromabcimportABCMeta,abstractmethodNOT_IMPLEMENTED="You should implement this."classCarElement(metaclass=ABCMeta):@abstractmethoddefaccept(self,visitor):raiseNotImplementedError(NOT_IMPLEMENTED)classBody(CarElement):defaccept(self,visitor):visitor.visitBody(self)classEngine(CarElement):defaccept(self,visitor):visitor.visitEngine(self)classWheel(CarElement):def__init__(self,name):self.name=namedefaccept(self,visitor):visitor.visitWheel(self)classCar(CarElement):def__init__(self):self.elements=[Wheel("front left"),Wheel("front right"),Wheel("back left"),Wheel("back right"),Body(),Engine()]defaccept(self,visitor):forelementinself.elements:element.accept(visitor)visitor.visitCar(self)classCarElementVisitor(metaclass=ABCMeta):@abstractmethoddefvisitBody(self,element):raiseNotImplementedError(NOT_IMPLEMENTED)@abstractmethoddefvisitEngine(self,element):raiseNotImplementedError(NOT_IMPLEMENTED)@abstractmethoddefvisitWheel(self,element):raiseNotImplementedError(NOT_IMPLEMENTED)@abstractmethoddefvisitCar(self,element):raiseNotImplementedError(NOT_IMPLEMENTED)classCarElementDoVisitor(CarElementVisitor):defvisitBody(self,body):print("Moving my body.")defvisitCar(self,car):print("Starting my car.")defvisitWheel(self,wheel):print("Kicking my {} wheel.".format(wheel.name))defvisitEngine(self,engine):print("Starting my engine.")classCarElementPrintVisitor(CarElementVisitor):defvisitBody(self,body):print("Visiting body.")defvisitCar(self,car):print("Visiting car.")defvisitWheel(self,wheel):print("Visiting {} wheel.".format(wheel.name))defvisitEngine(self,engine):print("Visiting engine.")car=Car()car.accept(CarElementPrintVisitor())car.accept(CarElementDoVisitor())

Output

Visiting front left wheel.Visiting front right wheel.Visiting back left wheel.Visiting back right wheel.Visiting body.Visiting engine.Visiting car.Kicking my front left wheel.Kicking my front right wheel.Kicking my back left wheel.Kicking my back right wheel.Moving my body.Starting my engine.Starting my car.

Abstraction

Using Python 3 or above allows to make a general implementation of the accept method:

classVisitable:defaccept(self,visitor):lookup="visit_"+type(self).__qualname__.replace(".","_")returngetattr(visitor,lookup)(self)

One could extend this to iterate over the class's method resolution order if they would like to fall back on already-implemented classes. They could also use the subclass hook feature to define the lookup in advance.

See also

Related Research Articles

In programming languages, a closure, also lexical closure or function closure, is a technique for implementing lexically scoped name binding in a language with first-class functions. Operationally, a closure is a record storing a function together with an environment. The environment is a mapping associating each free variable of the function with the value or reference to which the name was bound when the closure was created. Unlike a plain function, a closure allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.

In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.

The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently", introduced by the Gang of Four. The bridge uses encapsulation, aggregation, and can use inheritance to separate responsibilities into different classes.

In object oriented programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify their exact class. Rather than by calling a constructor, this is done by calling a factory method to create an object. Factory methods can either be specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes.

In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other instances of the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern as well as to the Open-Closed Principle, by allowing the functionality of a class to be extended without being modified. Decorator use can be more efficient than subclassing, because an object's behavior can be augmented without defining an entirely new object.

In software design and engineering, the observer pattern is a software design pattern in which an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

In computer programming, an iterator is an object that enables a programmer to traverse a container, particularly lists. Various types of iterators are often provided via a container's interface. Though the interface and semantics of a given iterator are fixed, iterators are often implemented in terms of the structures underlying a container implementation and are often tightly coupled to the container to enable the operational semantics of the iterator. An iterator performs traversal and also gives access to data elements in a container, but does not itself perform iteration.

In computer programming, a function object is a construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax. In some languages, particularly C++, function objects are often called functors.

In computer programming, the single-serving visitor pattern is a design pattern. Its intent is to optimise the implementation of a visitor that is allocated, used only once, and then deleted.

In computer programming, a callback is a function that is stored as data and designed to be called by another function – often back to the original abstraction layer.

<span class="mw-page-title-main">Method overriding</span> Language feature in object-oriented programming

Method overriding, in object-oriented programming, is a language feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its superclasses or parent classes. In addition to providing data-driven algorithm-determined parameters across virtual network interfaces, it also allows for a specific type of polymorphism (subtyping). The implementation in the subclass overrides (replaces) the implementation in the superclass by providing a method that has same name, same parameters or signature, and same return type as the method in the parent class. The version of a method that is executed will be determined by the object that is used to invoke it. If an object of a parent class is used to invoke the method, then the version in the parent class will be executed, but if an object of the subclass is used to invoke the method, then the version in the child class will be executed. This helps in preventing problems associated with differential relay analytics which would otherwise rely on a framework in which method overriding might be obviated. Some languages allow a programmer to prevent a method from being overridden.

In software engineering, double dispatch is a special form of multiple dispatch, and a mechanism that dispatches a function call to different concrete functions depending on the runtime types of two objects involved in the call. In most object-oriented systems, the concrete function that is called from a function call in the code depends on the dynamic type of a single object and therefore they are known as single dispatch calls, or simply virtual function calls.

In the Java computer programming language, an annotation is a form of syntactic metadata that can be added to Java source code. Classes, methods, variables, parameters and Java packages may be annotated. Like Javadoc tags, Java annotations can be read from source files. Unlike Javadoc tags, Java annotations can also be embedded in and read from Java class files generated by the Java compiler. This allows annotations to be retained by the Java virtual machine at run-time and read via reflection. It is possible to create meta-annotations out of the existing ones in Java.

<span class="mw-page-title-main">Python syntax and semantics</span> Set of rules defining correctly structured programs

The syntax of the Python programming language is the set of rules that defines how a Python program will be written and interpreted. The Python language has many similarities to Perl, C, and Java. However, there are some definite differences between the languages. It supports multiple programming paradigms, including structured, object-oriented programming, and functional programming, and boasts a dynamic type system and automatic memory management.

C++11 is a version of the ISO/IEC 14882 standard for the C++ programming language. C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14. The name follows the tradition of naming language versions by the publication year of the specification, though it was formerly named C++0x because it was expected to be published before 2010.

In computer programming, an anonymous function is a function definition that is not bound to an identifier. Anonymous functions are often arguments being passed to higher-order functions or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function. Anonymous functions are ubiquitous in functional programming languages and other languages with first-class functions, where they fulfil the same role for the function type as literals do for other data types.

In software engineering, a fluent interface is an object-oriented API whose design relies extensively on method chaining. Its goal is to increase code legibility by creating a domain-specific language (DSL). The term was coined in 2005 by Eric Evans and Martin Fowler.

In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (null) behavior. The null object design pattern, which describes the uses of such objects and their behavior, was first published as "Void Value" and later in the Pattern Languages of Program Design book series as "Null Object".

<span class="mw-page-title-main">Specification pattern</span> Software design pattern

In computer programming, the specification pattern is a particular software design pattern, whereby business rules can be recombined by chaining the business rules together using boolean logic. The pattern is frequently used in the context of domain-driven design.

In object-oriented programming, forwarding means that using a member of an object results in actually using the corresponding member of a different object: the use is forwarded to another object. Forwarding is used in a number of design patterns, where some members are forwarded to another object, while others are handled by the directly used object. The forwarding object is frequently called a wrapper object, and explicit forwarding members are called wrapper functions.

References

  1. 1 2 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software . Addison Wesley. pp.  331ff. ISBN   0-201-63361-2.{{cite book}}: CS1 maint: multiple names: authors list (link)
  2. Visitor pattern real-world example
  3. 1 2 3 4 Budd, Timothy (1997). An introduction to object-oriented programming (2nd ed.). Reading, Mass.: Addison-Wesley. ISBN   0-201-82419-1. OCLC   34788238.
  4. "The Visitor design pattern - Structure and Collaboration". w3sDesign.com. Retrieved 2017-08-12.
  5. Reddy, Martin (2011). API design for C++. Boston: Morgan Kaufmann. ISBN   978-0-12-385004-1. OCLC   704559821.