修改Moose属性方法

时间:2010-12-02 16:49:42

标签: perl attributes moose

我正在创建一个属性列表(超过下面显示的三个属性),所有属性都共享常用方法。是否可以在其中一个方法中添加触发器:

# 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.
    }
}

2 个答案:

答案 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
}