取消引用Moose属性中保存的内存中文件

时间:2011-09-05 16:19:45

标签: perl moose

以下是我正在尝试的一些代码的摘录:

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

我想我在这里缺少一些基本的东西。我应该如何将$buffer(内存中的文件)存储为Moose属性,以便我可以在以后检索它而不需要调用者取消引用它?

更新

我添加了一个around方法修饰符,可以解决这个问题:

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

......但它仍然感觉很乱。还有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

一个选项是通过添加下划线使两个属性(bufferold_stdout)变为私有,然后添加简单方法从外部访问缓冲区:

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

您还试图为Capture::Tiny或类似模块实现重复。

答案 1 :(得分:1)

请勿更改buffer的含义(与around一样),请创建新的访问者。

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