gpt4 book ai didi

perl - 我可以在构造时设置 Moose 对象属性的 'isa' 吗?

转载 作者:行者123 更新时间:2023-12-04 02:22:38 26 4
gpt4 key购买 nike

我有一个具有以下属性的 Moose 对象:

has 'people' => (
is => 'ro',
isa => 'ArrayRef[Person::Child]',
traits => ['Array'],
default => sub { [] },
handles => {
all_people => 'elements',
get_people => 'get',
push_people => 'push',
pop_people => 'pop',
count_people => 'count',
sort_people => 'sort',
grep_people => 'grep',
},
);

注意 isa 设置为 'ArrayRef[Person::Child]'。

我希望能够在创建对象时在 Person::ChildPerson::Adult 等之间进行选择。这可能还是我必须创建不同的对象,这些对象除了 people 属性的 isa 之外都是相同的?

(这让我想起了 Java generics )。

最佳答案

为什么不将该属性的定义移动到一个角色中并重用它呢?在其他类中进行适当的参数化?

package MyApp::Thingy::HasPeople;

use MooseX::Role::Parameterized;

parameter person_type => (
isa => 'Str',
required => 1,
);

role {
my $person_type = shift->person_type;

has 'people' => (
is => 'ro',
isa => "ArrayRef[${person_type}]",
traits => ['Array'],
default => sub { [] },
handles => {
all_people => 'elements',
get_people => 'get',
push_people => 'push',
pop_people => 'pop',
count_people => 'count',
sort_people => 'sort',
grep_people => 'grep',
},
);
};

1;

在其他地方,在实际需要该属性的类中

package MyApp::Thingy::WithChildren;
use Moose;

with 'MyApp::Thingy::HasPeople' => { person_type => 'Person::Child' };

1;

package MyApp::Thingy::WithAdults;
use Moose;

with 'MyApp::Thingy::HasPeople' => { person_type => 'Person::Adult' };

1;

这样你就可以不在两个地方维护属性,并且不会结束具有相同类但不同 API 的对象,这往往是一个漂亮的很大的代码味道。

或者,您可以简单地编写 ArrayRef 的子类型,它接受 Person::ChildPerson::Adult 的列表或您拥有的任何其他类型的人,但前提是该列表中的所有元素都属于同一类型。

use List::AllUtils 'all';
subtype 'PersonList', as 'ArrayRef', where {
my $class = blessed $_->[0];
$_->[0]->isa('Person') && all { blessed $_ eq $class } @{ $_ };
};

has persons => (
is => 'ro',
isa => 'PersonList',
...,
);

我可能会选择第一个解决方案,以便能够根据对象类来决定它是否包含 child 、成人或其他任何内容。

关于perl - 我可以在构造时设置 Moose 对象属性的 'isa' 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4164900/

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