2010-06-08 83 views
4

我試圖瞭解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'); 
} 

回答

7

巧得很,我曾經有在~/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

+0

感謝您的回覆。我正在運行x86_64,debian和perl 5.10。我還必須指出,據我所知,「字段」根本不被棄用。然而,自5.9以來,它的實現停止使用僞哈希來支持有限的哈希。而且,我也有一份Conways的OO Perl的副本;我當然知道「場地」和「基地」的替代方案。正如我所說的,我只是想了解編譯指示,並且缺少文檔。 – 2010-06-09 01:30:10

+2

@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

相關問題