【问题标题】:What's the best way to assign a method body at construction time when using Moose?使用 Moose 在构造时分配方法体的最佳方法是什么?
【发布时间】:2010-12-14 18:07:27
【问题描述】:

我正在使用Moose(特别是MooseX::Declare)创建一个迭代器对象Iter,它有一个next 方法,用于推进状态并根据需要返回0 或1 while 声明。我遇到的问题是,根据其中一个构造参数的存在,next 需要执行两组非常不同的操作。在我看来,我有五个选择:

  1. 如果……那么在next方法中
  2. 子类
  3. 散列调度
  4. 符号表操作
  5. 将方法放在不同的模块中,并在构建时加载所需的一种

一号只是业余爱好者。

第二个,我想,是正确的 OOP 做事方式。我不反对这样做,但仅仅覆盖单个方法似乎有点矫枉过正。

我过去经常使用 Number 3 在程序或伪功能上工作,这就是我现在正在做的事情。

4 号,众所周知,充满了危险,我对 Moose Guts 一无所知,不想在不必要的时候开始胡闹。

最后一项,number 5 在我看来是最明智的(也是 Perlish),但与 Number 2 一样,工作量有点太大了。我真的想知道是否有第五种我没有考虑过的方法,例如挂钩到元类或者可能是相当成熟的 MooseX 模块。

【问题讨论】:

  • 您可能想进一步解释迭代器应该执行的不同操作。在不了解完整用例的情况下很难提供设计建议。
  • 好吧,我真的在寻找最佳实践,而不是实现细节。我所拥有的工作正常,但是我真的想要在Moose 范式内执行散列调度吗?也就是说,这样做的“Moosy”方式是什么?

标签: perl moose


【解决方案1】:

将“下一个”子引用传递给构造函数并将其保存在属性中:

has next => (
    isa => 'CodeRef',
    required => 1,
    traits => ['Code'],
    handles => { next => 'execute_method' },
);

使用native attribute 'Code' trait 提供的'execute_method' 处理程序,您可以像普通方法一样调用'next' 方法,它会在属性中找到子引用主体。

如果您想预先定义子引用主体并在构建时决定使用哪个版本,您可以根据对象的其他条件在构建器子中设置“下一个”的值:

has next => (
    # ...
    lazy => 1,
    default => sub {
         my $self = shift;
         return sub { ... } if $self->some_condition;
         # etc etc...
    },
);

【讨论】:

  • 只是为了让任何阅读本文的人明白这一点,没有is => '..'、reader 或accessor 的事实是故意的。为委托方法赋予与属性相同的名称非常优雅——它准确地公开了所需的功能,同时将潜在的混淆降至最低。
【解决方案2】:

另一种选择是动态应用角色:

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);
}

【讨论】:

    猜你喜欢
    • 2017-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-19
    • 1970-01-01
    • 2021-12-19
    • 2014-05-20
    相关资源
    最近更新 更多