Generating Accessors with Closures
Most accessor methods do essentially the same thing: they simply fetch or store a value from that instance variable. In Perl, the most natural way to create a family of near-duplicate functions is looping around a closure. But closures are anonymous functions lacking names, and methods need to be named subroutines in the class’s package symbol table so that they can be called by name. This is no problem—just assign the closure reference to a typeglob of the appropriate name.
package Person;
sub new {
my $invocant = shift;
my $self = bless({}, ref $invocant || $invocant);
$self–>init();
return $self;
}
sub init {
my $self = shift;
$self–>name("unnamed");
$self–>race("unknown");
$self–>aliases([]);
}
for my $field (qw(name race aliases)) {
my $slot = _ _PACKAGE_ _ . "::$field";
no strict "refs"; # So symbolic ref to typeglob works.
*$slot = sub {
my $self = shift;
$self–>{$field} = shift if @_;
return $self–>{$field};
};
}Closures are the cleanest hand-rolled way to create a multitude of
accessor methods for your instance data. It’s efficient for both the
computer and you. Not only do all the accessors share the same bit of
code (they only need their own lexical pads), but later if you decide to
add another attribute, the changes required are minimal: just add one
more word to the for loop’s list, and
perhaps something to the init
method.
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access