Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Perl中本地更改类的属性_Perl_Oop_Scope_Lexical Scope - Fatal编程技术网

在Perl中本地更改类的属性

在Perl中本地更改类的属性,perl,oop,scope,lexical-scope,Perl,Oop,Scope,Lexical Scope,我在一个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 $obje

我在一个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();

有没有办法做到这一点?

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

让我们使用一个我知道有效的代码示例,并尝试解释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或文件创建范围(您的问题在那里)

如果您能够在没有方法调用的情况下直接访问元素(错误实践IMHO),那么您很可能能够在对象中定位该元素的范围

例如:

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();
name.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'};
    }
}
index.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";

这可能不像您要求的那么多封装,但是您可以
local
-将散列的属性化。这将输出
“CarlLennyCarl”


您还可以
local
-将整个方法化。这也会输出
“CarlLennyCarl”


一个简单但不起眼的破解方法是将原始值存储在作用域顶部的新变量中,完成自己的工作,然后在底部恢复原始值。如果您可以在块内部或块外部调用不同的方法(使用不同的实现),这将行得通。您根本不明白这个问题?不,误解了上下文。local、eval和许多perl关键字根据上下文做不同的事情。它没有点击问题是本地的,在方法调用中被调用,但是,您完全可以自己回答问题,而不只是发布到一个主题上进行斥责;)
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;