以下是我正在尝试的一些代码的摘录:
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( @_ );
};
......但它仍然感觉很乱。还有更好的方法吗?
答案 0 :(得分:1)
一个选项是通过添加下划线使两个属性(buffer
和old_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 };
}
},
},
);