5

Net::IP オブジェクトとして IP アドレスのリストを含むクラスを作成しています。

Net::IP オブジェクトをサブタイプ (IPAddress) としてラップし、文字列から IPAddress への強制を定義しました。次に、タイプ ArrayRef[IPAddress] の ip_list というクラスに属性を追加し、 Arrayトレイトのpushメソッドに委譲しました。

use MooseX::Declare;
use Moose::Util::TypeConstraints;

use Net::IP;

subtype 'IPAddress'
    => as 'Object'
    => where { $_->isa('Net::IP') };

coerce 'IPAddress'
    => from 'Str'
    => via { Net::IP->new( $_ ) };

class IPs {

    has 'ip_list' => ( traits  => ['Array'],
                       isa    => 'ArrayRef[IPAddress]',
                       is     => 'rw',
                       coerce => 1,
                       auto_deref => 1,
                       default => sub { [] },
                       handles => {
                           add_ip    => 'push'
                       }
                       );

}

ただし、委任されたメソッドを次のように呼び出そうとすると:

my $o = IPs->new();
$o->add_ip( '192.168.0.1' );

「Value SCALAR(0x8017e8) was not pass container type constraint 'IPAddress' at ...」というエラーが表示されます。

したがって、明らかに add_ip へのパラメーターは強制されていません。

私が試みていることを行うことは可能ですか、それともすべて手動で行う必要がありますか? 私は Moose のマニュアルを調べましたが、いずれかの方法を示すものは何も見当たりませんでしたが、おそらく何かが欠けています。

4

1 に答える 1

7

残念ながら、Moose は型強制を連鎖させません (これらを内部的に解析し、「正しいこと」を自動的に判断するのは非常に複雑です)、そのため、連鎖を自分で定義する必要があります

use Net::IP;

class_type 'Net::IP';

coerce 'Net::IP'
    => from 'Str'
    => via { Net::IP->new( $_ ) };

subtype 'ArrayRefOfIPAddresses'
    => as 'ArrayRef[Net::IP]';

coerce 'ArrayRefOfIPAddresses'
    => from 'ArrayRef[Str]'
    => via { [ map { Net::IP->new($_) } @$_ ] };

coerce 'ArrayRefOfIPAddresses'
    => from 'Str'
    => via { [ Net::IP->new($_) ] };

coerce 'ArrayRefOfIPAddresses'
    => from 'Net::IP'
    => via { [ $_ ] };

class IPs {

    has 'ip_list' => ( traits  => ['Array'],
                       isa    => 'ArrayRefOfIPAddresses',
                       # ... rest of declaration as before
                     );

}

PS。Array ネイティブ委任トレイトを使用しているため、回避することをお勧めしますauto_deref。代わりにハンドラーを追加します。

has ip_list => (
    is => 'bare',
    # ...
    handles => {
        # ...
        ip_list => 'elements',
    },
);
于 2010-10-20T16:27:41.950 に答える