gpt4 book ai didi

perl - '_var'私有(private)实例变量在什么情况下声明为 'use fields'?

转载 作者:行者123 更新时间:2023-12-05 00:06:41 27 4
gpt4 key购买 nike

我试图了解 fields 的行为编译指示,我发现 poorly documented , 关于带下划线前缀的字段。这是文档必须说的:

Field names that start with an underscore character are made private to the class and are not visible to subclasses. Inherited fields can be overridden but will generate a warning if used together with the -w switch.



根据我在下面的测试,这与其实际行为不一致。不仅是 _ -前缀字段在子类中可见,它们在外部类中也可见(除非我不明白“可见”的含义)。此外,直接访问受限哈希也可以正常工作。

在哪里可以找到有关 fields 行为的更多信息pragma,缺少源代码?
{
package Foo;
use strict;
use warnings;
use fields qw/a _b __c/;

sub new {
my ( $class ) = @_;
my Foo $self = fields::new($class);
$self->a = 1; $self->b = 2; $self->c = 3;
return $self;
}

sub a : lvalue { shift->{a} }
sub b : lvalue { shift->{_b} }
sub c : lvalue { shift->{__c} }
}
{
package Bar;
use base 'Foo';
use strict;
use warnings;
use Data::Dumper;

my $o = Bar->new;
print Dumper $o; ##$VAR1 = bless({'_b' => 2, '__c' => 3, 'a' => 1}, 'Foo');

$o->a = 4; $o->b = 5; $o->c = 6;
print Dumper $o; ##$VAR1 = bless({'_b' => 5, '__c' => 6, 'a' => 4}, 'Foo');

$o->{a} = 7; $o->{_b} = 8; $o->{__c} = 9;
print Dumper $o; ##$VAR1 = bless({'_b' => 8, '__c' => 9, 'a' => 7}, 'Foo');
}

最佳答案

巧合的是,我恰好在 ~/codescraps/fields/test.pl 中有一个测试脚本可以追溯到两年前,当时我尝试回答完全相同的问题。 :)

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

{
package Foo;
use fields qw(foo bar _Foo_private);
use private qw(_really_private);
sub new {
my Foo $self = shift;
unless (ref $self) {
$self = fields::new($self);
$self->{_Foo_private} = "this is Foo's secret";
}
$self->{foo} = 10;
$self->{bar} = 20;
return $self;
}
}

my $foo = Foo->new;
$foo->{foo} = 42;

# this will generate an error: field does not exist
#$foo->{zap} = 42;

print "_Foo_private: " . $foo->{_Foo_private} . "\n";
$foo->{_Foo_private} = 1;
print "_Foo_private: " . $foo->{_Foo_private} . "\n";

print "_really_private: " . $foo->{_really_private} . "\n";
$foo->{_really_private} = 1;
print "_really_private: " . $foo->{_really_private} . "\n";

print Dumper($foo);

# subclassing
{
package Bar;
use base 'Foo';
use fields qw(baz _Bar_private); # these fields not shared with Foo
sub new {
my $class = shift;
my $self = fields::new($class);
$self->SUPER::new(); # init base fields
$self->{baz} = 10; # init own fields
$self->{_Bar_private} = "this is Bar's secret";
return $self;
}
}

my $bar = Bar->new;
# these work fine
$bar->{foo} = 1;
$bar->{bar} = 1;
$bar->{_Bar_private} = 1;

# this will not work - underscored fields are not visible to children
$bar->{_Foo_private} = 1;

当我运行你的代码时,我得到了错误:
No such pseudo-hash field "_b" at test2.pl line 16.

(第 16 行是 sub b 的定义。)您在什么架构上运行它?使用字段 pragma 的对象不是简单的祝福 hashrefs —— 它们是祝福的 arrayrefs,例如当我修改你的构造函数看起来像这样:
sub new {
my ( $class ) = @_;
my Foo $self = fields::new($class);
$self->{a} = 1; $self->{_b} = 2; $self->{__c} = 3;
print "I look like: ", Data::Dumper::Dumper($self);
return $self;
}

我懂了:
I look like: $VAR1 = bless( [
bless( {
'a' => 1
}, 'pseudohash' ),
1,
2,
3
], 'Bar' );

作为附言,我觉得有必要指出 fields杂注和 base附带的编译指示都已被弃用,强烈建议避免使用它们。现在,如果你想用访问器构建一个漂亮的 OO 模块,可以使用 Class::Accessor或直接转至 Moose .

关于perl - '_var'私有(private)实例变量在什么情况下声明为 'use fields'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3001414/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com