我正在创建一个包含IP地址列表的类,如Net :: 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)没有在...处传递容器类型约束'IPAddress'”
很明显,add_ip的参数没有被强制执行。
是否有可能做我正在尝试的事情,或者我应该手动完成所有这些操作?我已经浏览了Moose手册,但我没有看到任何表明任何方式的东西,但我可能遗漏了一些东西。
答案 0 :(得分: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',
},
);