2011-02-12 6 views
4

Mooseでこれを行うことはできますか?言い換えればPerl/Mooseでは、相互依存のデフォルトを持つ2つの属性を持つことはできますか?

package SomeClass; 
use Moose; 

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

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

... 

は、私が「開始」と「終了」と呼ばれる2つの属性をしたい、そのうちの一つだけが指定されている場合、私は、もう一つは同じものに設定することにしたいです。いずれかを指定しないとエラーになります。

この相互依存セットアップは機能しますか?

+1

これはエラーを指定するのに失敗しませんが、そうでなければ動作するはずです。私はいずれかを指定することができず、そのうちの1つにアクセスすると無限の再帰を引き起こすと考えられます。しかし、それは検証するのが簡単なはずです。 – btilly

答えて

16

はい、あなたは、これらの値の少なくとも一方が指定されていることを確認することにより、無限再帰の可能性を排除場合:

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; 
} 

また、デフォルトの潜水艦にチェックを遅らせることができます:

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

最初のものは実際に動作しますか?私は、属性が設定され、必要に応じてデフォルトが適用された後にBUILDが呼び出されたと思いました。 –

2

個人的に、私は無限再帰に巻き込まれなかったことを確認するために怠惰を活用したい:

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; 
} 
関連する問題