#!/usr/bin/perluse warnings;{ package Simple::Tax; use Moose::Role; requires 'price'; sub calculate_tax { my $self = shift; return int($self->price * 0.05); }}{ package A; use Moose; use Moose::Util qw( apply_all_roles ); has price => ( is => "rw",isa => 'Int' ); #price in pennIEs sub new_with_simple_tax { my $class = shift; my $obj = $class->new(@_); apply_all_roles( $obj,"Simple::Tax" ); }}my $o = A->new_with_simple_tax(price => 100);print $o->calculate_tax," cents\n";
我的第二个想法是在包的主体中使用if语句来使用不同的语句:
#!/usr/bin/perluse warnings;{ package Complex::Tax; use Moose::Role; requires 'price'; sub calculate_tax { my $self = shift; #pretend this is more complex return int($self->price * 0.15); }}{ package Simple::Tax; use Moose::Role; requires 'price'; sub calculate_tax { my $self = shift; return int($self->price * 0.05); }}{ package A; use Moose; has price => ( is => "rw",isa => 'Int' ); #price in pennIEs if ($ENV{TEST_A}) { with "Simple::Tax"; } else { with "Complex::Tax"; }}my $o = A->new(price => 100);print $o->calculate_tax," cents\n";
其中一个比另一个更好,它们中的任何一个都有一些可怕的东西,还有一种我还没想过的更好的方法.
解决方法 我的第一个建议是像MooseX :: Traits,然后在对象创建时指定不同的角色:my $test = A->with_traits('Simple::Tax')->new(...);my $prod = A->with_traits('Complex::Tax')->new(...);
但是这打开了在没有应用角色的情况下创建A的大门.所以进一步思考,我认为你有一个X / Y问题.如果Simple :: Tax仅用于在测试环境中模拟Complex :: Tax,则可以执行多项 *** 作来覆盖Complex :: Tax实现.
例如,您可以像这样定义Simple :: Tax:
package Simple::Tax; use Moose::Role;requires 'calculate_tax';around calculate_tax => sub { int($_[1]->price * 0.05) };
然后总是使用A compose Complex :: Tax并仅在测试期间将Simple :: Tax应用于它(使用apply_all_roles).
但是,如果您在生产中需要Simple :: Tax和Complex :: Tax(而不仅仅是测试),那么最好的选择是从组合关系(确实)到委托关系(has)的重构.
package TaxCalculator::API; use Moose::Role; requires qw(calculate_tax); package SimpleTax::Calculator; use Moose; with qw(TaxCalculator::API); sub calculate_tax { ... } package ComplexTax::Calculator; use Moose; with qw(TaxCalculator::API); sub calcuate_tax { ... } package A; use Moose; has tax_calculator => ( does => 'TaxCalculator::API',handles => 'TaxCalculator::API',default => sub { ComplexTax::Calculator->new() },);
然后,如果你想覆盖它,你只需传入一个新的tax_calculator:
my $test = A->new(tax_calculator => SimpleTax::Calculator->new());my $prod = A->new(tax_calculator => ComplexTax::Calculator->new());
因为句柄会将角色中的所有方法委托为新代理,这几乎与自己编写角色相同.
总结以上是内存溢出为你收集整理的perl – 如何在Moose中处理模拟角色?全部内容,希望文章能够帮你解决perl – 如何在Moose中处理模拟角色?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)