【发布时间】:2018-09-10 19:47:07
【问题描述】:
我想在调用 BUILD 方法后将对象的属性更改为只读。我该怎么做?
(上下文:我的程序使用MooseX::YAML从YAML加载这个我想在创建后刻在石头上的对象,然后在BUILD方法中更改它的属性,以解决YAML的限制描述here。更具体地说,我的 YAML 代码声明了一个目录和它下面的一堆文件,但似乎没有办法在 YAML 中表示所有这些文件都必须在该目录中。当然,我可以预先添加这个目录名到所有这些文件名,使它们成为绝对的,但这意味着 1) 当我改变对目录位置的想法时,我必须更改这些文件的所有条目,而不是只更改目录名,并且2)在创建对象之前从程序内部更改目录名称会很痛苦并且容易出错。)
(稍后添加:)一个最小的工作示例。
yaml1:
# invalid YAML, unfortunately:
dir: &dir /here
file1: *dir/foo
file2: *dir/bar
# ... and a lot more
yaml2:
# works, but requires repeating '/here/':
dir: /here
file1: /here/foo
file2: /here/bar
# ...
yaml3:
# works, but requires making changes to attribute values:
dir: /here
file1: foo
file2: bar
# ...
program.perl:
use strict;
use warnings;
use lib '.';
use MooseX::YAML qw (LoadFile);
use Try::Tiny;
foreach (1..3) {
my $datafile = "yaml$_";
print STDERR "Loading $datafile...\n";
try {
LoadFile ("yaml$_");
} catch {
print STDERR "$_";
};
}
在一个目录中创建所有这些文件并从那里运行“perl program.perl”,我得到以下输出:
Loading yaml1...
YAML::XS::Load Error: The problem:
did not find expected alphabetic or numeric character
was found at document: 1, line: 2, column: 12
while scanning an alias at line: 2, column: 8
Loading yaml2...
Loading yaml3...
“mypkg.pm”文件显示了我在使用 yaml3 时必须对属性进行的更改。
mypkg.pm:
package mypkg;
use Moose;
use File::Spec;
has 'dir' => (isa => 'Str', is => 'ro');
# have to allow modifying these values in BUILD
# (!!)
has [qw (file1 file2)] => (isa => 'Str', is => 'rw');
sub BUILD {
my ($self) = @_;
$self->file1 (File::Spec->catfile ($self->dir, $self->file1));
$self->file2 (File::Spec->catfile ($self->dir, $self->file2));
# ... etc.
# everything done, I would like all further changes to the attribute
# values to be impossible from now on
}
__PACKAGE__->meta->make_immutable;
【问题讨论】: