2011-09-05 2 views
2

의 I는 실험있어 일부 코드에서 발췌 한 것입니다 : 다른 곳에서무스 특성에 개최 메모리 파일을 역 참조

has buffer  => (is => 'rw', isa => 'ScalarRef'); 
has old_stdout => (is => 'rw', isa => 'FileHandle'); 

sub capture { 
    my $self = shift; 
    my $old_stdout; 
    my $buffer; 

    open $old_stdout, '>&', STDOUT 
     or croak 'Cannot duplicate filehandle'; 

    close STDOUT; 

    open STDOUT, '>', \$buffer 
     or croak 'Cannot open filehandle'; 

    $self->old_stdout($old_stdout); 
    $self->buffer(\$buffer); 
} 

sub reset { 
    my $self = shift; 

    open STDOUT, '>&', $self->old_stdout 
     or croak 'Cannot reset STDOUT'; 
} 

: 나는 부정 행위 시도

my $stdout = Capture->new(); 
print "Some output\n"; 
$stdout->reset(); 

print $stdout->buffer(); 
# SCALAR(0x#######) 

print ${$stdout->buffer()}; 
# Some output 

은 속성 hashref를 직접 설정 - 작동하지만, 그것을하고 싶지 않다. :

open STDOUT, '>', \$self->{buffer} 
     or croak 'Cannot open filehandle'; 

나는 som을 놓치고 있다고 생각한다. 여기 근본적인 것. $buffer (메모리 내 파일)을 무스 (Moose) 속성으로 저장하는 방법은 어떻게해야합니까? 호출자가 역 참조를하지 않고 나중에 검색 할 수 있도록하려면 어떻게해야합니까?

업데이트

나는 트릭을 않는 around 방법 수정, 추가되었습니다 :

around 'buffer' => sub { 
    my $orig = shift; 
    my $self = shift; 
    return ${$self->$orig} unless @_; 
    $self->$orig(@_); 
}; 

을 ...하지만 여전히 지저분한 느낌. 더 좋은 방법이 있습니까?

답변

1

의 옵션은 밑줄을 앞에 붙이는 민간 특성 (bufferold_stdout)를 만든 다음 외부에서 버퍼를 액세스 할 수있는 간단한 방법을 추가하는 것입니다

sub buffer { 
    my $self = shift; 
    return ${$self->_buffer} 
} 

그것은 또한 당신이 중복을 구현하려고하는 것을 보면 Capture::Tiny 또는 이와 유사한 모듈.

+0

감사합니다. 당신의 대답에서 아무 것도 없애지 않고, 내가 그것을 보았 더라면 분명했습니다. 그것은 분명하고 간단하며 효과적입니다. capture :: Tiny - 네, 매우 유사합니다. 그것은 더 큰 무언가의 일부이며, 나는 Capture :: Tiny를 보았습니다. 나는 CPAN 모듈을 사용하여 잘 끝낼 수도 있지만, 어느 쪽이든, 그것은 가치있는 일이었습니다. 길을 따라 몇 가지 새로운 것들을 배웠습니다. – Martin

1

buffer의 의미를 변경하지 마십시오 (예 : around). 새 접근자를 만듭니다.

has buffer_ref => (
    ... 
    handles => { 
     buffer => sub { 
     my $self = shift; 
     if (@_) { 
      ${ $self->buffer_ref } = $_[0]; 
     } else { 
      return ${ $self->buffer_ref }; 
     } 
     }, 
    }, 
); 
+0

+1 그 일을하는 데 아주 멍청한 방법입니다. 나는 그것을 좋아한다. 그리고 이것은 본질적으로 똑같은 일을하는 bvr의 답변과 밀접한 연관이있다. 나는 위임을 사용하는 방법을 찾고 있었고, 당신의 예제는 코드 참조의 사용을 'handles'으로 명확하게하는 데 도움이되었습니다. 그러나, 나는 bvr의 솔루션이 더 간단하고 명확하고, "metaclass twiddling"(Moose 문서에서 인용)을 요구하지 않는다고 생각한다. – Martin

+0

@Martin, 나는 항상 접근자를'handles'에 넣습니다. 다른 임의의 서브와 함께 행성 주위의 절반보다 속성의 정의의 나머지 부분이 더 좋습니다. "열혈"이 없습니다. 하위 파일은 파일의 다른 위치와 동일합니다. – ikegami

+0

접근자를 속성 정의로 유지하는 것이 좋은 지적입니다. 대체 대답에 영향을 준 것은 마우스로 시도한 것이고 실패했습니다. 마우스가 내 질문의 일부가 아니란 점을 알고 있습니다.하지만 마우스가 도움이 될 수 있다는 것이 밝혀졌습니다. – Martin