5

我在我的一个 Perl 脚本中遇到了一个奇怪的问题。我有一个 Perl 对象。在某个范围内,我希望更改对象属性之一,但我希望该属性在离开范围后恢复为旧值。

例子:

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();

有没有办法实现这样的目标?

4

2 回答 2

6

这可能不像您要求的那样封装,但您可以local-ize 散列的属性。这输出"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;

您还可以local-ize 整个方法。这也输出"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;
于 2015-09-03T21:05:17.943 回答
-1

我完全误解了那里发生的事情。您不能在子例程调用中使用本地,这就是您遇到的问题。

让我们使用一个我知道有效的代码示例,并尝试解释 eval 实际在做什么。

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use Cwd;

print getcwd() . "\n";

eval{
        local @INC = ('/tmp');
        require 'test.pl';

        print 'local: ' . Dumper(\@INC);
};
print Dumper(\@INC);

这很有效,因为我正在修改一个变量,而不是调用另一个子程序来修改我的变量。

为了使其按预期工作,您必须创建对象的深层副本以在本地范围或类似范围内进行修改。(我很确定首先发生了什么)

local 为给定的括号、eval 或文件创建范围(你的问题在那里)

如果您能够在没有方法调用的情况下直接访问元素(糟糕的做法恕我直言),您可能能够本地化该元素在对象中的范围。

例子:

名称.pm:

package name;
use strict;
use warnings;

{

    sub new {
        my ($class,$name) = @_;
        my $self = bless {}, $class;
        $self->{'name'} = $name if defined $name;
        return $self;
    }

    sub name
    {
        my ($self,$name) = @_;
        $self->{'name'} = $name if defined $name;
        return $self->{'name'};
    }
}

索引.pl:

#!/usr/bin/perl -w
use strict;
use warnings FATAL => 'all';

use name;

my $obj = name->new('test');

print $obj->{'name'} . "\n";

{
    local $obj->{'name'} = 'test2';

    print $obj->{'name'} . "\n";
}

print $obj->{'name'} . "\n";
于 2015-09-03T20:38:10.310 回答