开发者

In Perl/Moose, can I have two attributes with mutually-dependent defaults?

Can I do this in Moose?

package SomeClass;
use Moose;

has start => (
    isa => 'Int',
    is => 'ro',
    lazy => 1,
    default => sub { $_[0]->end },
);

has end => (
    isa =&g开发者_运维知识库t; 'Int',
    is => 'ro',
    lazy => 1,
    default => sub { $_[0]->start },
);

...

In other words, I want two attributes called "start" and "end", and if only one of them is specified, I want the other one to be set to the same thing. Not specifying either one is an error.

Does this mutually-dependent setup work?


Yes, if you remove the possibility of infinite recursion by verifying that at least one of these values is specified:

has start => (
    ...
    predicate => 'has_start',
);

has end => (
    ...
    predicate => 'has_end',
);

sub BUILD
{
    my $self = shift;

    die "Need to specify at least one of 'start', 'end'!" if not $self->has_start and not $self->has_end;
}

Alternatively, you could delay the check to the default subs:

has start => (
    ...
    predicate => 'has_start',
    default => sub {
        my $self = shift;
        die "Need to specify at least one of 'start', 'end'!" if not $self->has_end;
        $self->end;
    },
);

has end => (
    ...
    predicate => 'has_end',
    default => sub {
        my $self = shift;
        die "Need to specify at least one of 'start', 'end'!" if not $self->has_start;
        $self->start;
    },
);


Personally, I'd take advantage of laziness to ensure that I didn't get caught in an infinite recursion:

has start => (
  is => 'ro',
  isa => 'Int',
  lazy => 1,
  default => sub { shift->end },
  predicate => 'has_start',
);

has end => (
  is => 'ro',
  isa => 'Int',
  lazy => 1,
  default => sub { shift->start },
  predicate => 'has_end',
);

sub BUILD {
  my $self = shift;

  die "Need to specify at least one of 'start', 'end'!" 
    unless $self->has_start || $self->has_end;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜