Perl 初始化后,我应该如何定义Moose对象子例程?
初始化后,我应该如何定义Moose对象子例程 我正在使用Moose编写一个对象模块,并计划序列化(Perl 初始化后,我应该如何定义Moose对象子例程?,perl,initialization,moose,Perl,Initialization,Moose,初始化后,我应该如何定义Moose对象子例程 我正在使用Moose编写一个对象模块,并计划序列化(nstore)创建的对象 检查以下(简化!)示例: 包装MyObj 0.001; 使用驼鹿; 使用namespace::autoclean; 具有“大小”=>( is=>“ro”, isa=>Int', 必需=>1, ); sub some_sub{ 我的($self,@more)=; 如果($self->size()size()size()selected子系统(@)。你觉得怎么样?也许是另一种情
nstore
)创建的对象
检查以下(简化!)示例:
包装MyObj 0.001;
使用驼鹿;
使用namespace::autoclean;
具有“大小”=>(
is=>“ro”,
isa=>Int',
必需=>1,
);
sub some_sub{
我的($self,@more)=;
如果($self->size()<100)#做点什么;
elsif(($self->size()<500))#做点别的;
elsif(($self->size()<7500))#做点别的;
# ...
}
1.
根据大小的不同,某些\u sub
的作用也不同。由于size
是只读的,因此在初始化对象后它保持不变
因此,假设我调用了无数次if
s,很遗憾每次我都要经历所有if
s
我最好在对象初始化后执行一次,然后将some\u sub
设置为一个更简单的函数,如果
s,则不使用
但是。。。我该怎么做
更新
也许我应该添加subref类型的lazy
属性,该属性将保存对所选子例程的引用一些子系统
然后只需调用$self->selected子系统(@)
。你觉得怎么样?也许是另一种情况!(对不起,我按相反的顺序阅读你的问题!)
例如:
use 5.012;
use warnings;
package MyObj 0.001;
use MooseX::SingletonMethod;
use namespace::autoclean;
has 'size' => (
is => 'ro',
isa => 'Int',
required => 1,
);
sub _which_sub {
my ($self) = @_;
if ($self->size < 100) { return sub{ 'A' } }
elsif ($self->size < 500) { return sub{ 'B' } }
elsif ($self->size < 7500) { return sub{ 'C' } }
return sub { 'D' };
}
package main;
my $obj = MyObj->new( size => 200 );
$obj->add_singleton_method( some_sub => $obj->_which_sub );
say $obj->some_sub; # => B
使用5.012;
使用警告;
包装MyObj 0.001;
使用MooseX::SingletonMethod;
使用namespace::autoclean;
具有“大小”=>(
is=>“ro”,
isa=>Int',
必需=>1,
);
sub\u哪个sub{
我的($self)=@;
如果($self->size<100){return sub{'A'}
elsif($self->size<500){return sub{'B'}
elsif($self->size<7500){return sub{'C'}
返回子{'D'};
}
主包装;
my$obj=MyObj->new(大小=>200);
$obj->add_singleton_方法(some_sub=>$obj->\u which_sub);
说$obj->some#sub;#=>B
应该可以从类内部添加这个单一的方法创建。请查看此博客文章以获得一些指导:。还有一大堆关于你的更新的帖子:
use 5.012;
use warnings;
package MyObj;
use Moose;
use namespace::autoclean;
has 'size' => (
is => 'ro',
isa => 'Int',
required => 1,
);
has 'chosen_sub' => (
is => 'ro',
isa => 'CodeRef',
lazy => 1,
builder => '_build_chosen_sub',
init_arg => undef, # unless want option of providing anon sub at construction?
);
sub _build_chosen_sub {
my ($self) = @_;
if ($self->size < 100) { return sub{ 'A' } }
elsif ($self->size < 500) { return sub{ 'B' } }
elsif ($self->size < 7500) { return sub{ 'C' } }
return sub { 'D' };
}
package main;
my $obj = MyObj->new( size => 200 );
say $obj->chosen_sub->(); # => B
使用5.012;
使用警告;
包装材料MyObj;
使用驼鹿;
使用namespace::autoclean;
具有“大小”=>(
is=>“ro”,
isa=>Int',
必需=>1,
);
已“选择_sub”=>(
is=>“ro”,
isa=>CodeRef',
懒惰=>1,
builder=>“\u build\u selected\u sub”,
init_arg=>undef,#除非希望在构造时提供一个非子节点选项?
);
子组件(构建)(选定)(子组件){
我的($self)=@;
如果($self->size<100){return sub{'A'}
elsif($self->size<500){return sub{'B'}
elsif($self->size<7500){return sub{'C'}
返回子{'D'};
}
主包装;
my$obj=MyObj->new(大小=>200);
说$obj->selected_sub->();#=>B
有计算方法=>(is=>'ro',lazy\u build=>1,init\u arg=>undef);
子构建计算方法{
我的$self=shift;
如果$self->size<100,则返回“\u calculate\u small”;
如果$self->size<500,则返回“\u calculate\u medium”;
如果$self->size<7500,则返回“\u calculate\u large”;
返回“_计算_巨大”;
}
子计算小{…}
子计算介质{…}
#等等。
子计算{
我的$self=shift;
my$method=$self->calculation\u method;
返回$self->$method(@);
}
另外,calculation\u方法
现在也可以序列化了。我不太喜欢它,因为我希望它对用户透明。这一切都应该在对象初始化期间发生。另请参阅我的更新,了解我对它的另一种看法。它可以做到这一点(提供的链接提供了一些关于这一点所需的重播的见解)。但是,如果您对$self->selected\u sub->(@))满意(@))
(关于:您的更新),那么请查看我的新答案。是否有理由我不满意$self->selected\u sub->(@))
。仅参考API,即使用$obj->selected_sub->(…)
而不是$obj->selected_sub(…)
顺便说一句,我认为构建器解决方案是最好的方法。请注意,本机代码属性trait具有“execute”和“execute\u method”委托,可用于轻松设置CodeRef属性,其行为类似于普通方法。@phaylon:很酷,以前从未见过这种情况。现在有了!。。。我认为您可以将'selected_sub'设为private(即更改为\u selected_sub
),然后添加sub mysub{my($self)=@;返回$self->\u selected_sub()->(@)}
。现在我们可以调用$obj->mysub()代码>。再看看,这就是hdp写的。是的,hdp的答案是最好的(+1)。我也在考虑写同样的东西,但目的是让它更接近你的更新,也就是说,我认为你想要/需要在他们的+1中使用anon sub。是的,这就是我更新的内容。您还可以将calculate()
方法折叠到calculate\u method
属性中(并将其重命名为s/\u method/
),方法是使其isa=>'CodeRef',traits=>['code'],handles=>{calculate=>'execute\u method'})代码>(正如费伦在德雷顿的回答中指出的那样)。
use 5.012;
use warnings;
package MyObj;
use Moose;
use namespace::autoclean;
has 'size' => (
is => 'ro',
isa => 'Int',
required => 1,
);
has 'chosen_sub' => (
is => 'ro',
isa => 'CodeRef',
lazy => 1,
builder => '_build_chosen_sub',
init_arg => undef, # unless want option of providing anon sub at construction?
);
sub _build_chosen_sub {
my ($self) = @_;
if ($self->size < 100) { return sub{ 'A' } }
elsif ($self->size < 500) { return sub{ 'B' } }
elsif ($self->size < 7500) { return sub{ 'C' } }
return sub { 'D' };
}
package main;
my $obj = MyObj->new( size => 200 );
say $obj->chosen_sub->(); # => B
has calculation_method => (is => 'ro', lazy_build => 1, init_arg => undef);
sub _build_calculation_method {
my $self = shift;
return '_calculate_small' if $self->size < 100;
return '_calculate_medium' if $self->size < 500;
return '_calculate_large' if $self->size < 7500;
return '_calculate_enormous';
}
sub _calculate_small { ... }
sub _calculate_medium { ... }
# etc.
sub calculate {
my $self = shift;
my $method = $self->calculation_method;
return $self->$method(@_);
}