我已经接触了Moose大约七个月了,Perl只稍微长了一点,但我无法理解如何通过为每个属性提供一个参数来构造类中的几个属性,而不是为它们提供一个完整的哈希引用。我搜索了大量的文档和网页,但我要么找错了词,要么遗漏了什么。
我已经调整了设计,使之更加通用。使用以下基本设置:
package First;
use Moose;
use Second::Type1;
use Second::Type2;
has 'type1' => (
is => 'rw',
isa => 'Second::Type1',
default => sub {Second::Type1->new(name => 'random')}
);
has 'type2' => (
is => 'rw',
isa => 'Second::Type2',
default => sub {Second::Type2->new(name => 'random')}
);
package Second::Type1;
use Moose;
use This;
has 'name' => (
is => 'rw',
isa => 'Str',
required => 1,
);
has 'this' => (
is => 'rw',
isa => 'This',
default => sub {This->new()}
);
# package has more attributes, but you get the idea
__PACKAGE__->meta->make_immutable();
no Moose;
1;
package Second::Type2;
use Moose;
use That;
has 'name' => (
is => 'rw',
isa => 'Str',
required => 1,
);
has 'that' => (
is => 'rw',
isa => 'That',
default => sub {That->new()}
);
# package has more attributes, but you get the idea
__PACKAGE__->meta->make_immutable();
no Moose;
1;我想先说一句:
use First;
my $first = First->new(type1 => 'foo', type2 => 'bar');其中'foo‘等于秒的值::Type2 1’s‘s 'name’属性,'bar‘等于第二:Type2 2’s 'name‘属性的值。
现在,关于我自己的解决方案,我已经(成功地)做了一个驼鹿::角色,它只包含一个‘BUILDARGS’子,然后使用一个Factory类(其中的内容在这里不相关,海事组织):
package Role::SingleBuildargs;
use Moose::Role;
use Factory::Second;
requires 'get_supported_args';
around BUILDARGS => sub {
my ($class, $self, %args) = @_;
my @supported_args = $self->get_supported_args;
my $factory = Factory::Second->new();
my @errors = ();
foreach my $arg (sort {$a cmp $b} keys %args) {
if (grep {$_ eq $arg} @supported_args) {
my $val = $args{$arg};
if (!ref $val) { # passed scalar init_arg
print "$self (BUILDARGS): passed scalar\n";
print "Building a Second with type '$arg' and name '$val'\n";
$args{$arg} = $factory->create(type => $arg, name => $val)
} elsif (ref $val eq 'HASH') { # passed hashref init_arg
print "$self (BUILDARGS): passed hashref:\n";
my %init_args = %$val;
delete $init_args{name} unless $init_args{name};
$init_args{type} = $arg;
$args{$arg} = $factory->create(%init_args);
} else { # passed another ref entirely
print "$self (BUILDARGS): cannot handle reference of type: ", ref $val, "\n";
die;
}
} else {
push @errors, "$self - Unsupported attribute: '$arg'";
}
}
if (@errors) {
print join("\n", @errors), "\n";
die;
}
return $self->$class(%args);
};
no Moose;
1;然后我在第一个类和其他类中使用这个角色,比如第一个。
我也试过通过以下方式胁迫:
package Role::Second::TypeConstraints;
use Moose::Util::TypeConstraints
subtype 'SecondType1', as 'Second::Type1';
subtype 'SecondType2', as 'Second::Type2';
coerce 'SecondType1', from 'Str', via {Second::Type1->new(name => $_};
coerce 'SecondType2', from 'Str', via {Second::Type2->new(name => $_};
no Moose::Util::TypeConstraints;
1;并修改了第一个包(仅列出更改):
use Role::Second::TypeConstraints;
has 'type1' => (
isa => 'SecondType1',
coerce => 1,
);
has 'type2' => (
isa => 'SecondType2',
coerce => 1,
); 然而,这是行不通的。如果有人能解释原因,那就太好了。
至于实际的问题:在你的课堂上获得这种行为的最好方法是什么?真的没有比修改BUILDARGS更好的方法了,还是我错过了什么(关于Moose::Util::TypeConstraint,也许)?TMTOWTDI和所有的,但我的似乎根本没有效率。
编辑:为一致性而编辑(混淆了通用类名)
发布于 2015-06-26 13:46:19
你可以完全按照你描述的那样使用强制
First、Second::Type1和Second::Type2Second::Type1添加强制操作
从'Str‘=>到{ =>::Type1 1->new(名称=> $_ ) };
以及Second::Type2
从'Str‘=>到{ =>::Type2 2->new(名称=> $_ ) };type1和type2属性First的强制
有'type1‘=> ( is => 'rw',isa =>’new::Type2 1‘,默认=>子{Second::Type2 1->new },胁迫=> 1,);有'type2’=> ( is => 'rw',isa =>‘秒::Type2 2’,默认=> sub{Second:Type2 2->new },胁迫=> 1,);然后,您可以按照您所说的那样创建一个First对象。
my $first = First->new(type1 => 'foo', type2 => 'bar');发布于 2015-06-26 13:38:45
你绝对可以用类型和强制来做。尝试使用MooseX::类型而不是内置的。
这里有一个小例子,部分是从MooseX::Types docs中提出来的。
package Foo;
use Moose;
use MooseX::Types -declare => [qw(MyDateTime)];
use MooseX::Types::Moose 'Int';
use DateTime;
class_type MyDateTime, { class => 'DateTime' };
coerce MyDateTime, from Int, via { DateTime->from_epoch( epoch => $_ ) };
has date => (
is => 'ro',
isa => MyDateTime,
default => sub {time},
coerce => 1,
);
package main;
my $foo = Foo->new;
say 'without args: ', $foo->date;
my $bar = Foo->new( date => time - 24 * 3600 );
say 'with args: ', $bar->date;这将打印如下内容:
without args: 2015-06-26T13:35:38
with args: 2015-06-25T13:35:38它看起来很像你所拥有的,只是使用新类型的东西。试试看。
https://stackoverflow.com/questions/31073018
复制相似问题