Создание обязательных атрибутов во время строительства - PullRequest
2 голосов
/ 29 марта 2012

Предположим, я хочу такой класс:

package Restraint;
use Moose;

has ball => (
    is   => 'ro',
    does => 'Heavy',
);

has chain => (
    is   => 'ro',
    does => 'Lockable',
);

has ball_class => (
    is   => 'ro',
    isa  => 'Str',
);

has chain_class => (
    is   => 'ro',
    isa  => 'Str',
);

1;

Теперь я хочу создать экземпляр класса:

my $r = Restraint->new(
    ball_class = 'Ball',
    chain_class = 'Chain',
);

оба аргумента являются обязательными.

Я также хочу создать экземпляры ball_class и chain_class во время построения и назначить их соответствующим атрибутам, чтобы, наконец, я мог, например, $r->ball->lift или $r->chain->lock и т. Д.

Как мне это сделать?

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

Просто пометьте их обоих как «обязательные» - см. Moose :: Manual :: Attributes

Это ничего не даст для «шара» или «цепочки».Нет никакой связи.

Вы можете настроить шарик / цепочку с ленивыми строителями, которые будут ссылаться на ваши имена классов (см. Руководство по Moose снова.)хотя они напрямую:

my $r = Restraint->new(
  ball  => CannonBall->new(...),
  chain => IronChain->new(...)
);

ОК - вы не хотите передавать объекты.В таком случае вам нужны ленивые строители.Пометьте мяч как ленивый и дайте ему строителя, а лось позвонит строителю, когда мяч будет использован впервые.http://metacpan.org/pod/Moose::Cookbook::Basics::Recipe3

Не торопитесь, чтобы прочитать документацию по лося - ее много, но она написана довольно хорошо и охватывает множество функций.Много примеров.

package Restraint;
use Moose;

has ball => (
    is => 'ro',
    does => 'Heavy',
    lazy => 1,
    builder => '_build_ball'
);

has ball_class => (
   is => 'ro',
   required => 1
);

sub _build_ball {
   my $self = shift;
   my $ball_class = $self->ball_class;
   return $ball_class->new();
}
1 голос
/ 29 марта 2012

Использование BUILD для создания экземпляров при установке required только для *_class атрибутов, кажется, работает в некоторой степени, за исключением того, что:

  • Мне пришлось сделать ball и chain чтение-запись

Код:

package Restraint;
use Moose;

has ball => (
    is   => 'rw',
    does => 'Heavy',
);

has chain => (
    is   => 'rw',
    does => 'Lockable',
);

has ball_class => (
    is   => 'ro',
    isa  => 'Str',
    required => 1,
);

has chain_class => (
    is   => 'ro',
    isa  => 'Str',
    required => 1,
);

sub BUILD {
    my $self = shift;

    my $ball = $self->ball_class->new();
    $self->ball( $ball );
    my $chain = $self->chain_class->new();
    $self->chain( $chain );
}

1;

Пока это не большая жертва, но я все еще задаюсь вопросом, есть ли более правильный путь, хотя.

...