我正在创建一个属性列表(超过下面显示的三个属性),所有属性都共享常用方法。是否可以在其中一个方法中添加触发器:
# Create a bunch of attributes
for my $attr ( qw( title name address ) ) {
has $attr => ( is => 'rw', isa => 'Str' );
around $attr => sub {
# more stuff here.
}
}
# Add a trigger
has_another_method 'title' => ( trigger => \&_trigger_title );
我知道我可以获得有关属性的元信息,但我没有找到任何可以让我更改属性方法的东西(也许是有充分理由的)。能够做到这一点有助于保持我的代码干净,并且意味着公共位都在一个地方定义。如果没有,我可以单独创建属性,并包含触发方法。
答案清楚地表明,在创建属性后更改属性并不是一个好主意。相反,我选择了一种不同的方法,允许我将所有属性选项保存在一个地方。这个例子有点简单,但它证明了这个想法:
# Create a bunch of attributes
for my $attr ( qw( title name address ) ) {
my %options = ( is => 'rw', isa => 'Str' );
# Add a trigger to the title attribute.
$options{ 'trigger' } = \&_trigger_title
if $attr eq 'title';
has $attr => ( %options );
around $attr => sub {
# more stuff here.
}
}
答案 0 :(得分:2)
触发器只是属性的一个属性,但它们被定义为只读。你可以 find_meta( $attribute )->get_attribute('trigger')->set_value( $attribute, sub { new trigger })
,但你真的打破了封装。
我只是在for循环中声明所有常用属性,然后在其他地方声明特殊情况。
答案 1 :(得分:2)
属性方法在构造时组成,因此在使用has
指令创建它时,通常可以使用所有选项。 然而,目前没有什么特别的触发方法,所以你可以这样做,以绕过'触发'选项的只读:
my $attr = __PACKAGE__->meta->get_attribute('title')->meta->get_attribute('trigger')->set_raw_value('_trigger_sub_name');
然而,这正在深深地钻研到驼鹿的内脏;如果实现发生变化,你可以成为SOL(加上你会因为某种原因而违反约束)。因此将触发器设置为 更好
has $_ => (
is => 'rw', isa => 'Str',
trigger => '_trigger_' . $_,
) for (qw(title name address));
sub _trigger_title {
# implementation here
}
sub _trigger_name {
# implementation here
}
sub _trigger_address {
# implementation here
}