Я хотел бы создать структурированный тип в Moose, который можно использовать в качестве типа для другого атрибута Moose. Например, я хотел бы иметь возможность создать атрибут name
, который имеет свои собственные атрибуты value
и error
.
Поэтому я хотел бы знать, как лучше всего этого достичь. Я создал рабочий пример, определив простой класс Moose для представления универсального объекта Field
. Это имеет атрибуты value
и error
. Затем я создал еще один класс Moose для объекта Person
. Это имеет атрибуты id
и name
, оба из которых имеют тип Field
:
Определить объект общего поля:
package MyApp::Type::Field;
use Moose;
use namespace::autoclean;
has 'value' => ( is => 'rw' );
has 'error' => ( is => 'rw', isa => 'Str' );
__PACKAGE__->meta->make_immutable;
1;
Определите объект Person, который использует объект поля:
package MyApp::Person;
use Moose;
use namespace::autoclean;
use MyApp::Type::Field;
has 'id' => ( is => 'rw', isa => 'MyApp::Type::Field' );
has 'name' => ( is => 'rw', isa => 'MyApp::Type::Field' );
__PACKAGE__->meta->make_immutable;
1;
Сделайте что-нибудь с объектом Person:
package MyApp::Test;
use Moose;
use namespace::autoclean;
use MyApp::Person;
my $person = MyApp::Person->new();
# This works.
$person->id( MyApp::Type::Field->new() );
$person->id->value( 1 );
$person->id->error( 'Not found' );
# This fails as the name object has not yet been defined.
$person->name->value( 'Dave' );
# Can't call method "value" on an undefined value at ...
__PACKAGE__->meta->make_immutable;
1;
Это работает, но в MyApp::Test
я хотел бы иметь возможность прямого доступа к value
и error
атрибутам name
и id
этого человека без необходимости сначала создавать новый объект MyApp::Type::Field
для каждого из атрибутов человека.
Или, иначе говоря, я бы предпочел, чтобы пользователю класса Person
не приходилось делать это: $person->id( MyApp::Type::Field->new() );
, прежде чем он смог использовать атрибут id
.
Есть ли хороший чистый способ, которым я могу этого достичь?