通过自学Moose的方式,我正在研究一个与特定硬件接口的Moose对象.所述硬件采用许多不同的命令来设置硬件的各种属性,设置PROPERTYNAME=VALUE器的所有形式以及PROPERTYNAME?吸气器(注意这些"设置器"和"吸气器"在硬件的网络接口上).我想要做的是创建一个对象,其中硬件的所有这些属性都使用类似属性的接口实现.由于获取和设置各种属性对所有属性采用相同的形式,是否有办法从这些属性的列表中自动生成setter和getter?
IE:而不是这个:
Package MyHardware;
use Moose;
has property1 => (
'is' => 'rw',
'reader' => 'set_property1',
'writer' => 'get_property1',
);
has property2 => (
'is' => 'rw',
'reader' => 'set_property2',
'writer' => 'get_property2',
);
# ...
has propertyN => (
'is' => 'rw',
'reader' => 'set_propertyN',
'writer' => 'get_propertyN',
);
Run Code Online (Sandbox Code Playgroud)
有什么我可以这样做:
Package MyHardware;
use Moose;
attributes => (
'is' => 'rw',
'names' => [qw/property1 property2 ... propertyN/],
'reader' => sub {
my $self = shift;
my $property = shift;
return $self->_send_command("$property?");
},
'writer' => sub {
my $self = shift;
my $property = shift;
my $value = shift;
return $self->_send_command("$property=$value");
},
);
Run Code Online (Sandbox Code Playgroud)
编辑:这就是我想要发生的事情:
# CALLER:
my $hw = MyHardware->new();
$hw->property1('foo');
print $hw->property2 . "\n";
Run Code Online (Sandbox Code Playgroud)
而"引擎盖下":
$hw->property1('foo');
# Becomes
sub { return $hw->_send_command('property1=foo'); }
# And
$hw->property2();
# Becomes
sub { return $hw->_send_command('property2?'); }
Run Code Online (Sandbox Code Playgroud)
循环遍历属性怎么样?
use strict;
use warnings;
use Moose;
foreach my $prop ( qw( property1 property2 property3 property4 ) ) {
has $prop => (
is => 'rw',
isa => 'Str',
reader => "get_$prop",
writer => "set_$prop",
);
}
1;
Run Code Online (Sandbox Code Playgroud)
弄清楚了。我意识到我根本不应该使用属性来执行此操作。相反,我将使用Class::MOP::Class动态生成方法,如下所示:
my $meta = Class::MOP::Class->initialize(__PACKAGE__);
foreach my $prop (qw/property1 property2 property3/) {
$meta->add_method(qq/set_$prop/, sub {
my $self = shift;
my $value = shift;
return $self->_send_command(qq/$prop=$value/);
}
);
$meta->add_method(qq/get_$prop/, sub {
my $self = shift;
return $self->_send_command(qq/$prop?/);
}
);
}
Run Code Online (Sandbox Code Playgroud)
通过调用 has() 来执行此操作将有效地将对象状态放在两个位置 - 硬件上和实例中 - 而我只希望它位于一个位置。