This sounds like something for which code references would be more suitable.
After reading up on the Visitor pattern — I wasn't familiar with it by name — I dare say it *is* something for which code references would be more suitable. The example on that paged could be implemented as follows in Perl:
use strict;
use warnings;
{
package Wheel;
sub new {
my ($class, $name) = @_;
return bless({ name => $name }, $class);
}
sub get_name { my ($self) = @_; return $self->{name}; }
sub accept { my ($self, $visitor) = @_; $visitor->($self); }
}
{
package Engine;
sub new { my ($class) = @_; return bless({}, $class); }
sub accept { my ($self, $visitor) = @_; $visitor->($self); }
}
{
package Body;
sub new { my ($class) = @_; return bless({}, $class); }
sub accept { my ($self, $visitor) = @_; $visitor->($self); }
}
{
package Car;
sub new {
my ($class) = @_;
return bless({
engine => Engine->new(),
body => Body->new(),
wheels => [ map { Wheel->new($_) }
'front left',
'front right',
'back left',
'back right',
],
}, $class);
}
sub accept {
my ($self, $visitor) = @_;
$visitor->($self);
$self->{engine}->accept($visitor);
$self->{body}->accept($visitor);
$_->accept($visitor) foreach @{$self->{wheels}};
}
}
sub visitor {
my ($o) = @_;
if ($o->isa('Wheel')) {
print("Visiting ", $o->get_name(), " wheel\n");
}
elsif ($o->isa('Body')) {
print("Visiting body\n");
}
elsif ($o->isa('Engine')) {
print("Visiting engine\n");
}
elsif ($o->isa('Car')) {
print("Visiting car\n");
}
else {
die("Unknown class " . ref($o));
}
}
{
my $car = Car->new();
$car->accept(\&visitor);
}
|