2010-06-08 1 views
4

poorly documented이라는 fieldspragma의 동작을 이해하려고하는데 밑줄이있는 필드가 있습니다. 이 문서 그것에 대해 말을하는 것입니다 :어떤 상황에서 '필드 사용'에서 '_var'로 선언 된 인스턴스 변수가 비공개입니까?

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.

이 아래, 내 테스트에 따르면, 실제 동작과 일치하지 않습니다. 서브 클래스 내에서 _ -prefixed 필드를 볼 수있을뿐만 아니라 외국 클래스에서도 볼 수 있습니다 ('보이는'의미가없는 한). 또한, 제한된 해시에 직접 액세스하면 올바르게 작동합니다.

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'); 
} 

답변

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에 대한 정의입니다.) 당신이 어떤 아키텍처에서 실행을? 필드 pragma를 사용하는 객체는 단순 축복 해시 레프가 아닙니다. 축약 된 배열 참조입니다 (예 : 나는 당신의 생성자를 수정하면 다음과 같이보고 :

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으로 직접 이동하십시오.

+0

답장을 보내 주셔서 감사합니다. x86_64, debian 및 perl 5.10을 실행하고 있습니다. 내가 아는 한,'fields'는 전혀 사용되지 않습니다. 그러나, 5.9 이후, 구현은 제한된 해시를 선호하여 가상 해시 사용을 중단했습니다. 그리고 나는 Conways의 OO Perl을 가지고있다. 나는 '들판들'과 '기지들'에 대한 대안을 확실히 알고 있습니다. 내가 말했듯이, 나는 단지 pragma를 이해하기를 원하며, 문서는 부족하다. –

+2

@ 페드로 : 예, 꽤 오랫동안 사용할 수 있지만 더 이상 지원되지는 않습니다. 나는 실제로'fields'에 대해서 다음과 같이 질문했다. http://stackoverflow.com/questions/1168644/why-is-the-fields-pragma-incompatible-with-multiple-inheritance-in-perl - - 그리고 같은 "사용 무스 대신"대답. :) – Ether