再次遇到Moose对象模型的问题。我不确定在这里发布或更好地发布" codereview" - 先在这里尝试......;)
Region
。Spot
(s)。name
和一些Entries
。id
,content
,flag
。API应该如下:
my $region = Region->new; #create a Region
my $sx = $region->spot('x'); #return the Spot with a name 'x'
#if the spot with a name 'x' doesn't exists, create it
$sx->add(id => 'id1', content => 'content1', flag => 'f1'); #add a new Entry to Spot 'x'
$sx->add(id => 'id2', content => sub { return "string" }, flag => 'f2');#add another Entry
$sx->render; # render the "spot" - do some operations on array of Entries
我已经拥有的东西 - 对于长期来源 - 我将它缩短为最小的工作包。
首先 - 为"条目提供一个简单的类"。
package Region::Entry;
use namespace::sweep;
use Modern::Perl;
use Moose;
has 'id' => (is => 'rw', isa => 'Str');
has 'content' => (is => 'rw', isa => 'Str|CodeRef');
has 'flag' => (is => 'rw', isa => 'Str');
__PACKAGE__->meta->make_immutable;
1;
Region的类 - 只有一个HashRef用于按spotname存储Spots(作为键)
package Region;
use namespace::sweep;
use Modern::Perl;
use Moose;
use Method::Signatures::Simple;
use Region::Spot;
has 'spots' => (
traits => ['Hash'],
is => 'rw',
isa => 'HashRef[Region::Spot]',
default => sub { {} },
handles => {
set_spot => 'set',
get_spot => 'get',
spot_exists => 'exists',
},
);
method spot {
my $name = shift;
return undef unless $name;
$self->set_spot($name => Region::Spot->new()) unless $self->spot_exists($name);
return $self->get_spot($name);
}
__PACKAGE__->meta->make_immutable;
1;
最后为Spots上课
package Region::Spot;
use Modern::Perl;
use namespace::sweep;
use Moose;
use Method::Signatures::Simple;
use Region::Entry;
has 'entries' => (
traits => ['Array'],
is => 'rw',
isa => 'ArrayRef[Region::Entry]',
default => sub { [] },
handles => {
add_entry => 'push',
},
);
#PROBLEM HERE - HOW TO IMPLEMENT THIS for allow attributes as in the above API
#so add(id=>'id', content => 'xxxx', flag => 'f');
#with correct attribute checking????
method add {
#$self->add_entry....
}
method render {
#...
return "rendered entries";
}
__PACKAGE__->meta->make_immutable;
1;
因此,在实施add
API时遇到问题。见上面的评论...
$sx->add(id => 'id1', content => 'content1', flag => 'f1'); #add a new Entry to Spot 'x'
我的对象模型或它的实现可能是错误的,因为我在课堂上有add
方法,但是没有定义类型......或者不知道。 ..
每次创建任何新内容时,这都是我的问题。我知道"如何使用Moose" (我不是专家,但知道基础知识) - 但问题是定义正确的类...... :(
我希望上面的内容更有意义......并且为长篇文章而烦恼。
答案 0 :(得分:1)
我可能会遗漏您问题的一些微妙细节,但为什么不在您的add
方法中解压缩参数并创建新的Entry
?
method add {
$self->add_entry( Entry->new( @_ ) );
}
答案 1 :(得分:1)
警告:未经测试的代码
如果您打算以这种方式设置API,则可以在创建new
时将属性传递到Region::Entry
method add {
my %params = @_;
$self->add_entry( Region::Entry->new(\%params) );
}
另外,你可以
$sx->add( Region::Entry->new( { id => ..., } );
.
.
.
method add {
my $self = shift;
$self->add_entry( shift );
}