什么情况下,实例变量在'use fields'中声明为'_var'为private?
问题描述:
我试图了解fields
编译指示的行为,我发现poorly documented,有关以下划线开头的字段。这是文档要说的:什么情况下,实例变量在'use fields'中声明为'_var'为private?
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
编译指示行为的更多信息,缺少源代码?
{
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行是次b中的定义。)你运行这个什么架构上?使用字段杂注的对象不是简单的祝福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编译那与此同时,都被弃用,强烈要求避免使用它们。如今,如果您打算使用访问器构建一个漂亮的面向对象模块,您可以使用Class::Accessor或直接转至Moose。
感谢您的回复。我正在运行x86_64,debian和perl 5.10。我还必须指出,据我所知,“字段”根本不被弃用。然而,自5.9以来,它的实现停止使用伪哈希来支持有限的哈希。而且,我也有一份Conways的OO Perl的副本;我当然知道“场地”和“基地”的替代方案。正如我所说的,我只是想了解编译指示,并且缺少文档。 – 2010-06-09 01:30:10
@Pedro:是的,他们可以使用相当长的一段时间,但不再真正支持;我实际上在这里问了一个关于'fields'的问题,我自己,一会儿回来:http://stackoverflow.com/questions/1168644/why-is-the-fields-pragma-incompatible-with-multiple-inheritance-in-perl - - 并得到相同的“使用穆斯代替”回复。 :) – Ether 2010-06-09 06:10:08