使用 Moose 时在构造时分配方法体的最佳方法是什么?

发布于 2024-10-07 17:57:40 字数 788 浏览 10 评论 0原文

我正在使用 Moose (特别是 MooseX::Declare)创建一个迭代器对象 Iter,它有一个 next > 方法,根据 while 语句中使用的需要,推进状态并返回 01。我遇到的问题是,根据构造参数之一的存在,next 需要执行两组截然不同的操作。在我看来,我有五个选项:

  1. if ...then 在 next 方法
  2. 中子类
  3. 哈希调度
  4. 符号表操作
  5. 将方法放在不同的模块中,并在构造时加载所需的方法

Number 1只是业余爱好者。

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

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

众所周知,4 充满了危险,而且我不知道 Moose Guts 会在不必要的时候开始胡闹。

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

I'm using Moose (specifically MooseX::Declare) to create an iterator object, Iter which has a next method that advances state and returns 0 or 1 as required for use in a while statement. The problem I'm running into is that depending on the existence of one of the construction parameters, next needs to perform two very different sets of operations. The way I see it I have five options:

  1. if ... then in next method
  2. subclass
  3. hash dispatch
  4. symbol table manipulation
  5. put methods in different modules and load required one at construction time

Number 1 is just amateur.

Number 2 is, I suppose, the proper OOP way of doing things. I have no objections to doing it that way but seems a little bit overkill simply to override a single method.

I've often used Number 3 in the past when working procedurally or pseudo-functionally and it's what I'm doing now.

Number 4 is, as we all know, fraught with peril and I know nothing about Moose Guts to want to start messing around when unnecessary.

The last item, number 5 seems to me to be the most sensible (and Perlish) but like Number 2, is a little too much work. I'm really wondering if there's a fifth way I haven't considered such as hooking into the metaclass or perhaps a MooseX module that is reasonably mature.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云淡月浅 2024-10-14 17:57:46

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

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

Another option is to dynamically apply a role:

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);
}
遮云壑 2024-10-14 17:57:45

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

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

使用 原生属性'Code'特征,你可以像普通方法一样调用'next'方法,它会在属性中找到subref主体。

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

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

Pass your 'next' subref into the constructor and save it in an attribute:

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

With the 'execute_method' handler provided by the native attribute 'Code' trait, you can call the 'next' method as a normal method and it will find the subref body in the attribute.

If you want to pre-define the subref body/ies and decide at construction time which version to use, you could set the value of 'next' in a builder sub according to other conditions of the object:

has next => (
    # ...
    lazy => 1,
    default => sub {
         my $self = shift;
         return sub { ... } if $self->some_condition;
         # etc etc...
    },
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文