...">

Can I set the "isa" attribute of a Moose object attribute when building?

I have a Moose object with the following attribute:

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',
 },
);

Please note: isaset as "ArrayRef [Person :: Child]".

I would like to be able to choose between Person::Child, Person::Adultetc. when creating my object. Is this possible, or should I create different objects that will be identical except for the isaattribute people?

(This reminds me of Java generics ).

+3
source share
2 answers

Why not move the definition of this attribute to a role and reuse it, corresponding to parameterization, in other classes?

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::Child, Person::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',
    ...,
);

, , , - .

+5

Java, :

package Interfaces::Person;

use Moose::Role;

requires qw( list all attributes or methods that you require );

1;

, Person:: Adult Person:: Child :

package Person::Adult;

...
# add at the end
with qw(Interfaces::Person);

1;

package Person::Child;

...
# add at the end
with qw(Interfaces::Person);

1;

:

package My::People;
use Moose;
use MooseX::Types::Moose qw( ArrayRef );
use MooseX::Types::Implements qw( Implements );

has 'people' => (
 is      => 'ro',
 isa     => ArrayRef[Implements[qw(Interfaces::Person)]],
 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

Source: https://habr.com/ru/post/1774519/


All Articles