我正在编写一个脚本来帮助我精通Moose。我有以下代码:
package Dir;
use Moose;
use Modern::Perl;
use File;
has 'dirs' => (is => 'ro', isa => 'HashRef[Dir]' );
has 'files' => (is => 'ro', isa => 'HashRef[File]');
has 'dir_class' => (is => 'ro', isa => 'ClassName', default => 'Dir');
has 'file_class' => (is => 'ro', isa => 'ClassName', default => 'File');
sub BUILD {
my $self = shift;
my $path = $self->path;
my $name = $self->name;
my (%dirs, %files);
# populate dirs attribute with LaborData::Data::Dir objects
opendir my $dh, $path or die "Can't opendir '$path': $!";
# Get files and dirs and separate them out
my @dirs_and_files = grep { ! m{^\.$|^\.\.$} } readdir $dh;
closedir $dh or die "Can't closedir '$path': $!";
my @dir_names = grep { -d "$path/$_" } grep { !m{^\.} } @dirs_and_files;
my @file_names = grep { -f "$path/$_" } grep { !m{^\.} } @dirs_and_files;
# Create objects
map { $dirs{$_} = $self->dir_class->new ( path => $path . '/' . $_ ) } @dir_names;
map { $files{$_} = $self->file_class->new ( path => $path . '/' . $_ ) } @file_names;
# Set attributes
$self->dirs ( \%dirs );
$self->files ( \%files );
}
代码会导致以下错误:died: Moose::Exception::CannotAssignValueToReadOnlyAccessor (Cannot assign a value to a read-only accessor at reader Dir::dirs
要解决此错误,我可以为rw
和builder
属性设置属性dirs
或使用files
方法。前一种解决方案是不可取的,后一种解决方案需要重复代码(例如,目录需要打开两次),因此也是不可取的。
这个问题的最佳解决方案是什么?
答案 0 :(得分:2)
您可以将a writer
分配给只读属性,并在BUILD
内部使用该属性。使用_
命名它以表明它是内部的。
package Foo;
use Moose;
has bar => ( is => 'ro', writer => '_set_bar' );
sub BUILD {
my $self = shift;
$self->_set_bar('foobar');
}
package main;
Foo->new;
这不会引发异常。
它与制作rw
基本相同,但现在作者与读者的访问者不同。 _
表示它是内部的,因此它比仅使用rw
更不可取。请记住,无论如何,你无法真正保护Perl中的任何东西。如果您的用户想要进入内部,他们会。
答案 1 :(得分:-2)
我找到了一个可能的解决方案,尽管它不赞成:
# Set attributes
$self->{dirs} = \%dirs;
$self->{files} = \%files;