2009-08-04 13 views
1

모듈을 확장 중이므로 우수 사례에 대한 팁을 원합니다. 특히 네임 스페이스 충돌 : 정확히 무엇이며 어떻게 피하는 지.Perl 하위 클래스에서 인스턴스 데이터에 어떻게 액세스해야합니까?

확장 할 때 SUPER 클래스의 변수에 액세스하지 말고 접근 자나 객체 메소드를 통해서만 상태를 변경해야합니까? 접근 자 (또는 제한된 접근 자)가없는 경우 어떻게해야합니까? 이러한 객체 변수에 직접 액세스 할 수 있습니까?

건배!

답변

6

접근자를 통해서만 액세스하는 것이 가장 좋습니다. 이렇게하면 수퍼 클래스의 구현이 변경되어 하위 클래스에 영향을주지 않기 때문입니다. 언더 바 (underbar)로 시작하는 것은 멀리 떨어져 있어야합니다. 이러한 것들은 수업에 비공개입니다. 문서화되지 않은 것을 멀리하려고 시도하십시오. 그 일에 의지하면 문제가 생길 수 있습니다. 또한, has-a 대 is-a 관계를 사용하는 것을 고려하십시오.

위젯 클래스를 상상해 봅시다.

package Widget; 

use strict; 
use warnings; 

sub new { 
    my $class = shift; 
    my %args = @_; 

    return bless { 
     price => $args{price} || 0, 
     name => $args{name} || "unkown", 
    }, $class; 
} 

sub price { shift->{price} } 
sub name { shift->{name} } 

1; 

당신은 위젯을 서브 클래스로 결정 :이 클래스는 이름과 가격 멤버 (참고,이 중 어느 것도 내가 그냥이 예를 위해 그것에 대해 생각을 가진 버전으로 던져했다, 특히 좋은 코드 없음)이있다 가중치 구성원을 추가하려면 :

package Widget::WithWeight; 

use strict; 
use warnings; 

use base 'Widget'; 

sub new { 
    my $class = shift; 
    my %args = @_; 
    my $self = $class->SUPER::new(%args); 
    $self->{weight} = $args{weight} || 0; 
    return bless $self, $class; 
} 

sub weight { shift->{weight} } 

sub price_per_pound { 
    my $self = shift; 
    return $self->{price}/$self->{weight}; 
} 

1; 

이제 첫 번째 모듈 작성자가 가격 저장 방법에 대한 생각을 바꾼 것을 상상해보십시오. 아마도 그것은 부동 소수점 숫자로 저장되고 저자는 동전의 정수로 저장하는 것이 더 나을 것이라는 점을 깨달았다

갑자기
package Widget; 

use strict; 
use warnings; 

sub new { 
    my $class = shift; 
    my %args = @_; 

    if ($args{price}) {   
     $args{price} =~ s/[.]//; 
    } 

    return bless { 
     price => $args{price} || "000", 
     name => $args{name} || "unkown", 
    }, $class; 
} 

sub price { 
    my $self = shift; 
    my $price = $self->{price}; 
    substr($price, -2, 0) = "."; 
    return $price; 
} 

sub name { shift->{name} } 

1; 

, 당신의 검사 결과가 실패 시작되지만 대신 price 접근을 사용했다면 , 당신은 그 변화로부터 격리되었을 것입니다.

+0

나는 예를 들어,하지만, 내가 직접 몇 가지 변수의 내부 표현에 접근하고는 _foobar 방법을 사용하지 않은 : $ 셀프 = { '속성'= 실제 값이 같은 해시 심판으로 저장됩니다 > {objnum => NUM, type => TYPE, value => VALUE}, } $ self -> {property}와 같이 $ self를 통해 직접 '속성'에 액세스하면 안됩니까? get_property() 접근자를 가지고있는 경우에만 액세스해야합니까? 설치 스크립트에서 SUPER 클래스 모듈의 certaing 버전을 수행하는 것이 멍청한 일입니까? –

+0

언더 바 (예 :'$ self -> {_ property}')가있는 해시에 저장되지 않은 경우 공정한 게임이지만 접근 방법이 더 안전한 방법입니다 (구현 변경으로부터 보호 할 수 있습니다). –

1

두 모듈을 하나의 모듈로 상속하고 둘 모두 동일한 서브 모듈을 제공 (내보내기)하면 네임 스페이스 충돌이 발생할 수 있습니다.

클래스 및 역할을 제공하는 Perl 확장 인 Moose를 살펴 보시기 바랍니다. 역할을 사용하면 많은 충돌을 피할 수 있습니다. http://www.iinteractive.com/moose/

Moose는 클래스 변수에 대한 자동 접근자를 만들어 상속하는 클래스에서 액세스하는 것이 더 안전하도록 만듭니다.

+0

두 모듈을 상속하지 않으므로 문제가되지 않습니다. 나는 무스 역할에 대해 들었습니다. 실제로 흥미로운 것 같습니다. 그러나 확장하고있는 모듈은 내 것이 아니기 때문에 (저자가 아니기 때문에) 내 하위 클래스에 접근자를 생성하기 위해 무스를 사용하지 않아도됩니다. 제안에 감사드립니다. –

+2

참고로,'Moose' 클래스가 아닌'Moose' 클래스를 서브 클래스화할 수 있습니다. 나는 MooseX :: Declare'를 바닐라 무스에 제안 할 것이다. 훨씬 좋네요. –

+0

내가 의미하는 바는 Foo :: Bar 클래스를 만들고 있는데 Foo 클래스를 만들지 않았다. Foo 클래스는 데이터에 접근자를 구현하지 않는 클래스이다. 나는 저자와 연락을하고 정확히 그가 왜 그 데이터를 파고하기를 원하지 않는지를 볼 것입니다 ... 비록 moosex 팁을 주셔서 감사합니다! –

관련 문제