在构造期间实例化强制属性

时间:2012-03-29 11:21:59

标签: perl constructor moose

假设我想要一个这样的课程:

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_classchain_class,并将它们分配给相应的属性,以便最终我可以例如$r->ball->lift$r->chain->lock等。

我该怎么做?

2 个答案:

答案 0 :(得分:3)

只需将它们标记为“必需” - 请参阅Moose :: Manual :: Attributes

但是,对于“球”或“链”,这不会做任何事情。没有联系。

您可以使用惰性构建器设置球/链,这些构建器将引用您的类名(请再次参阅Moose手册)。

我可能只需要制作所需的对象并直接传递它们:

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

好的 - 您不想传入对象。在这种情况下,你需要懒惰的构建器。将球标记为懒惰并给它一个建造者,当球首次使用时,穆斯将召唤建造者。

http://metacpan.org/pod/Moose

http://metacpan.org/pod/Moose::Manual::Attributes

http://metacpan.org/pod/Moose::Cookbook::Basics::Recipe3

请花些时间阅读moose文档 - 这里有很多文档,但编写得很好并且涵盖了很多功能。很多例子。

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 :(得分:1)

仅在required属性设置*_class时使用BUILD进行实例化似乎在某种程度上有效,除了:

  • 我必须让ballchain读写

代码:

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;

现在这不是一个很大的牺牲,但我仍然想知道是否有更正确的方法。