gpt4 book ai didi

perl - Moose 从单个参数构造对象

转载 作者:行者123 更新时间:2023-12-01 02:08:08 25 4
gpt4 key购买 nike

我已经涉足 Moose 大约七个月,而 Perl 只是稍微长一点,但无法弄清楚如何通过为每个属性提供一个参数而不是它们的整个 hashref 来构造一个类中的多个属性。我已经广泛搜索了文档和网络,但我要么在寻找错误的词,要么遗漏了一些东西。

我已经调整了设计,使其更通用。使用以下基本设置:

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”等于 Second::Type1 的“name”属性的值,“bar”等于 Second::Type2 的“name”属性的值。

现在至于我自己的解决方案,我已经(成功地)制作了一个 Moose::Role,它只包含一个“围绕 BUILDARGS”的子,然后使用一个 Factory 类(其内容在 IMO 中不相关):
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;

然后我在 First 类和其他类(如 First)中使用该角色。

我也尝试通过以下方式进行强制:
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,
);

然而这并没有奏效。如果有人能解释原因,那就太好了。

至于实际问题:在您的类(class)中获得这种行为的最佳方法是什么?真的没有比修改 BUILDARGS 更好的方法,还是我错过了什么(关于 Moose::Util::TypeConstraints,也许)? TMTOWTDI 和所有,但我的似乎根本没有效率。

编辑:为一致性进行编辑(混合通用类名)

最佳答案

您可以完全按照您描述的方式使用强制转换

  • 添加
    use Moose::Util::TypeConstraints;

    First , Second::Type1Second::Type2
  • Second::Type1 添加强制操作
    coerce 'Second::Type1'
    => from 'Str'
    => via { Second::Type1->new( name => $_ ) };

    并到 Second::Type2
    coerce 'Second::Type2'
    => from 'Str'
    => via { Second::Type2->new( name => $_ ) };
  • type1 启用强制转换和 type2 First 的属性
    has 'type1' => (
    is => 'rw',
    isa => 'Second::Type1',
    default => sub { Second::Type1->new },
    coerce => 1,
    );

    has 'type2' => (
    is => 'rw',
    isa => 'Second::Type2',
    default => sub { Second::Type2->new },
    coerce => 1,
    );

  • 然后你可以创建一个 First完全按照你说的反对
    my $first = First->new(type1 => 'foo', type2 => 'bar');

    关于perl - Moose 从单个参数构造对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31073018/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com