Visitor pattern: Difference between revisions
Content added Content deleted
m (→{{header|Wren}}: Changed to Wren S/H) |
(Ada implementation with tagged types) |
||
Line 35: | Line 35: | ||
<br> |
<br> |
||
=={{header|Ada}}== |
|||
An Ada implementation of the Wikipedia Java example. |
|||
===Method 1: via Tagged Types (the object-oriented approach)=== |
|||
Perhaps more packages than needed (7), which makes for quite a few files (specification + implementation). Only the `Visitors` files are long; the rest are much shorter. |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
package Base is |
|||
type Base_Record is abstract tagged null record; |
|||
end Base; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
limited with Base; |
|||
limited with Bodies; |
|||
limited with Cars; |
|||
limited with Engines; |
|||
limited with Wheels; |
|||
package Visitors is |
|||
type Visitor is abstract tagged null record; |
|||
procedure Visit_Base |
|||
(Self : Visitor; Dest : Base.Base_Record'Class) is null; |
|||
procedure Visit_Body (Self : Visitor; Dest : Bodies.Body_Record'Class); |
|||
procedure Visit_Car (Self : Visitor; Dest : Cars.Car_Record'Class); |
|||
procedure Visit_Engine (Self : Visitor; Dest : Engines.Engine_Record'Class); |
|||
procedure Visit_Wheel (Self : Visitor; Dest : Wheels.Wheel_Record'Class); |
|||
type Perform is new Visitor with null record; |
|||
type Print is new Visitor with null record; |
|||
overriding procedure Visit_Body |
|||
(Self : Perform; Dest : Bodies.Body_Record'Class); |
|||
overriding procedure Visit_Body |
|||
(Self : Print; Dest : Bodies.Body_Record'Class); |
|||
overriding procedure Visit_Car |
|||
(Self : Perform; Dest : Cars.Car_Record'Class); |
|||
overriding procedure Visit_Car (Self : Print; Dest : Cars.Car_Record'Class); |
|||
overriding procedure Visit_Engine |
|||
(Self : Perform; Dest : Engines.Engine_Record'Class); |
|||
overriding procedure Visit_Engine |
|||
(Self : Print; Dest : Engines.Engine_Record'Class); |
|||
overriding procedure Visit_Wheel |
|||
(Self : Perform; Dest : Wheels.Wheel_Record'Class); |
|||
overriding procedure Visit_Wheel |
|||
(Self : Print; Dest : Wheels.Wheel_Record'Class); |
|||
end Visitors; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Ada.Text_IO; |
|||
with Ada.Strings.Unbounded; |
|||
use all type Ada.Strings.Unbounded.Unbounded_String; |
|||
with Wheels; |
|||
package body Visitors is |
|||
package IO renames Ada.Text_IO; |
|||
procedure Visit_Body (Self : Visitor; Dest : Bodies.Body_Record'Class) is |
|||
begin |
|||
Self.Visit_Body (Dest); |
|||
end Visit_Body; |
|||
overriding procedure Visit_Body |
|||
(Self : Perform; Dest : Bodies.Body_Record'Class) |
|||
is |
|||
begin |
|||
IO.Put_Line ("Moving my Body"); |
|||
end Visit_Body; |
|||
overriding procedure Visit_Body |
|||
(Self : Print; Dest : Bodies.Body_Record'Class) |
|||
is |
|||
begin |
|||
IO.Put_Line ("Visiting Body"); |
|||
end Visit_Body; |
|||
procedure Visit_Car (Self : Visitor; Dest : Cars.Car_Record'Class) is |
|||
begin |
|||
Self.Visit_Car (Dest); |
|||
end Visit_Car; |
|||
overriding procedure Visit_Car |
|||
(Self : Perform; Dest : Cars.Car_Record'Class) |
|||
is |
|||
begin |
|||
IO.Put_Line ("Starting my car"); |
|||
end Visit_Car; |
|||
overriding procedure Visit_Car (Self : Print; Dest : Cars.Car_Record'Class) |
|||
is |
|||
begin |
|||
IO.Put_Line ("Visiting Car"); |
|||
end Visit_Car; |
|||
procedure Visit_Engine (Self : Visitor; Dest : Engines.Engine_Record'Class) |
|||
is |
|||
begin |
|||
Self.Visit_Engine (Dest); |
|||
end Visit_Engine; |
|||
overriding procedure Visit_Engine |
|||
(Self : Perform; Dest : Engines.Engine_Record'Class) |
|||
is |
|||
begin |
|||
IO.Put_Line ("Revving my Engine"); |
|||
end Visit_Engine; |
|||
overriding procedure Visit_Engine |
|||
(Self : Print; Dest : Engines.Engine_Record'Class) |
|||
is |
|||
begin |
|||
IO.Put_Line ("Visiting Engine"); |
|||
end Visit_Engine; |
|||
procedure Visit_Wheel (Self : Visitor; Dest : Wheels.Wheel_Record'Class) is |
|||
begin |
|||
Self.Visit_Wheel (Dest); |
|||
end Visit_Wheel; |
|||
overriding procedure Visit_Wheel |
|||
(Self : Perform; Dest : Wheels.Wheel_Record'Class) |
|||
is |
|||
begin |
|||
IO.Put_Line ("Rolling my " & To_String (Dest.Name) & " wheel"); |
|||
end Visit_Wheel; |
|||
overriding procedure Visit_Wheel |
|||
(Self : Print; Dest : Wheels.Wheel_Record'Class) |
|||
is |
|||
begin |
|||
IO.Put_Line ("Visiting " & To_String (Dest.Name) & " wheel"); |
|||
end Visit_Wheel; |
|||
end Visitors; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Base; |
|||
limited with Visitors; |
|||
package Bodies is |
|||
type Body_Record is new Base.Base_Record with private; |
|||
procedure Visit (Self : Body_Record; Visitor : Visitors.Visitor'Class); |
|||
private |
|||
type Body_Record is new Base.Base_Record with null record; |
|||
end Bodies; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Visitors; |
|||
package body Bodies is |
|||
procedure Visit (Self : Body_Record; Visitor : Visitors.Visitor'Class) is |
|||
begin |
|||
Visitor.Visit_Body (Self); |
|||
end Visit; |
|||
end Bodies; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Base; |
|||
with Bodies; |
|||
with Engines; |
|||
with Wheels; |
|||
limited with Visitors; |
|||
package Cars is |
|||
type Car_Record is new Base.Base_Record with private; |
|||
procedure Visit (Self : Car_Record; Visitor : Visitors.Visitor'Class); |
|||
function Initialize return Car_Record; |
|||
private |
|||
type Wheel_Array is array (1 .. 4) of Wheels.Wheel_Record; |
|||
type Car_Record is new Base.Base_Record with record |
|||
Bod : Bodies.Body_Record; |
|||
Eng : Engines.Engine_Record; |
|||
Whs : Wheel_Array; |
|||
end record; |
|||
end Cars; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Ada.Strings.Unbounded; |
|||
with Visitors; |
|||
package body Cars is |
|||
subtype Unbounded_String is Ada.Strings.Unbounded.Unbounded_String; |
|||
use all type Unbounded_String; |
|||
procedure Visit (Self : Car_Record; Visitor : Visitors.Visitor'Class) is |
|||
begin |
|||
Visitor.Visit_Car (Self); |
|||
Visitor.Visit_Body (Self.Bod); |
|||
Visitor.Visit_Engine (Self.Eng); |
|||
for Wheel of Self.Whs loop |
|||
Visitor.Visit_Wheel (Wheel); |
|||
end loop; |
|||
end Visit; |
|||
function Initialize return Car_Record is |
|||
Result : Car_Record; |
|||
begin |
|||
Result.Whs := |
|||
[Wheels.Initialize (To_Unbounded_String ("front left")), |
|||
Wheels.Initialize (To_Unbounded_String ("front right")), |
|||
Wheels.Initialize (To_Unbounded_String ("back left")), |
|||
Wheels.Initialize (To_Unbounded_String ("back right"))]; |
|||
return Result; |
|||
end Initialize; |
|||
end Cars; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Base; |
|||
limited with Visitors; |
|||
package Engines is |
|||
type Engine_Record is new Base.Base_Record with private; |
|||
procedure Visit (Self : Engine_Record; Visitor : Visitors.Visitor'Class); |
|||
private |
|||
type Engine_Record is new Base.Base_Record with null record; |
|||
end Engines; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Visitors; |
|||
package body Engines is |
|||
procedure Visit (Self : Engine_Record; Visitor : Visitors.Visitor'Class) is |
|||
begin |
|||
Visitor.Visit_Engine (Self); |
|||
end Visit; |
|||
end Engines; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Ada.Strings.Unbounded; |
|||
with Base; |
|||
limited with Visitors; |
|||
package Wheels is |
|||
subtype Unbounded_String is Ada.Strings.Unbounded.Unbounded_String; |
|||
use all type Unbounded_String; |
|||
type Wheel_Record is new Base.Base_Record with private; |
|||
procedure Visit (Self : Wheel_Record; Visitor : Visitors.Visitor'Class); |
|||
function Initialize (Name : Unbounded_String) return Wheel_Record; |
|||
function Name (Me : Wheel_Record) return Unbounded_String; |
|||
private |
|||
type Wheel_Record is new Base.Base_Record with record |
|||
My_Name : Unbounded_String; |
|||
end record; |
|||
end Wheels; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Visitors; |
|||
package body Wheels is |
|||
procedure Visit (Self : Wheel_Record; Visitor : Visitors.Visitor'Class) is |
|||
begin |
|||
Visitor.Visit_Wheel (Self); |
|||
end Visit; |
|||
function Initialize (Name : Unbounded_String) return Wheel_Record is |
|||
(My_Name => Name); |
|||
function Name (Me : Wheel_Record) return Unbounded_String is (Me.My_Name); |
|||
end Wheels; |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">pragma Ada_2022; |
|||
with Cars; |
|||
with Visitors; |
|||
procedure Visitor_Pattern is |
|||
Car : Cars.Car_Record := Cars.Initialize; |
|||
Performer : aliased Visitors.Perform; |
|||
Printer : aliased Visitors.Print; |
|||
begin |
|||
Car.Visit (Performer); |
|||
Car.Visit (Printer); |
|||
end Visitor_Pattern; |
|||
</syntaxhighlight> |
|||
===Method 2: Discriminated Types=== |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
<syntaxhighlight lang="julia">abstract type CarElementVisitor end |
<syntaxhighlight lang="julia">abstract type CarElementVisitor end |