Search code examples
perloopscopelexical-scope

Locally change an attribute of a class in Perl


I have come across an odd problem in one of my Perl scripts. I have a Perl object. Within a certain scope I want one of the objects attributes to be changed, but I want the attribute to be restored to it's old value after it leaves the scope.

Example:

my $object = Object->new('name' => 'Bob');
{
     # I know this doesn't work, but it is the best way
     # I can represent what I amd trying to do.
     local $object->name('Lenny');

     # Prints "Lenny"
     print $object->name();
}

# Prints "Bob"
print $object->name();

Is there a way to achieve something like this?


Solution

  • This might not be as much encapsulation as you were asking for, but you can local-ize an attribute of a hash. This outputs "CarlLennyCarl"

    sub Object::new { bless { _name => $_[1] }, $_[0] } }
    sub Object::name { $_[0]->{_name} }
    
    my $obj = Object->new("Carl");
    print $obj->name;
    {
        local $obj->{_name} = "Lenny";
        print $obj->name;
    }
    print $obj->name;
    

    You could also local-ize the entire method. This also outputs "CarlLennyCarl":

    sub Object::new { bless { _name => $_[1] }, $_[0] } }
    sub Object::name { $_[0]->{_name} }
    
    my $obj = Object->new("Carl");
    print $obj->name;
    {
        local *Object::name = sub { "Lenny" };
        print $obj->name;
    }
    print $obj->name;