我正在使用Moose
(特别是MooseX::Declare
)创建一个迭代器对象Iter
,该对象具有一个next
方法,可以提升状态并返回0
或1
根据while
声明的要求使用。我遇到的问题是,根据其中一个构造参数的存在,next
需要执行两组非常不同的操作。我看到它的方式我有五个选择:
next
方法1号只是业余爱好者。
我认为2号是正确的OOP做事方式。我不反对这样做,但似乎有点矫枉过正,只是覆盖一个方法。
我过去经常使用 3号进行程序性或伪功能性处理,而这正是我现在正在做的事情。
众所周知,4号充满了危险,我对Moose Guts一无所知,希望在不必要的时候开始搞乱。
最后一项, 5号在我看来是最明智的(和Perlish)但是像2号一样,有点太多了。我真的很想知道是否有第五种方法我没有考虑过如同挂钩到元类,或者是一个相当成熟的MooseX
模块。
答案 0 :(得分:10)
将“next”subref传递给构造函数并将其保存在属性中:
has next => (
isa => 'CodeRef',
required => 1,
traits => ['Code'],
handles => { next => 'execute_method' },
);
使用native attribute 'Code' trait提供的'execute_method'处理程序,您可以将'next'方法作为普通方法调用,它将在属性中找到subref主体。
如果要预先定义subref主体并在构造时确定要使用的版本,可以根据对象的其他条件在构建器子中设置“next”的值:
has next => (
# ...
lazy => 1,
default => sub {
my $self = shift;
return sub { ... } if $self->some_condition;
# etc etc...
},
);
答案 1 :(得分:0)
另一种选择是动态应用角色:
package Iter;
use Moose;
use Moose::Util qw(apply_all_roles);
has next_role => (is => 'ro');
sub BUILD {
my $self = shift;
apply_all_roles($self, $self->next_role);
}